2014 summer 多校1

A:HDU4861html

描述:桌子上k个球,他们的权值分别是 (i=1,2,...,k) ball is 1^i+2^i+...+(p-1)^i (mod p),p是素数ios

两人轮流在剩下的中选一个拿,直到没有球,A是否拿的权值最多?ide

代码:测试

首先A先手,那么奇数个球,从小到大的顺序排依次拿,确定是A赢ui

惟一的A不赢的可能性:每种价值的球都是偶数个,这样依次拿,两我的拿的就同样多了spa

一开始输出测试了不少组数据,发现直接看仍是很差找规律啊,只要把赢的K,P输出来,就很容易看了.net

 1 #include <iostream>
 2 #include <stdio.h>
 3 #include <math.h>
 4 #include <string.h>
 5 using namespace std;
 6 
 7 int k,p;
 8 int a[104];
 9 //void solve(){
10 //    int ans=0;
11 //    for(int i=1;i<=k;i++){
12 //        ans=0;
13 //        for(int j=1;j<=p-1;j++){
14 //            ans+=(int)pow(j,i);
15 //        }
16 //        a[i]=(ans%p+p)%p;
17 //    }
18 //    for(int i=1;i<=k;i++){
19 //        cout<<a[i]<<" ";
20 //    }
21 //    cout<<endl;
22 //}
23 int main()
24 {
25     while(~scanf("%d%d",&k,&p)){
26 //        solve();
27          int s=k/(p-1);
28          if(s%2==1) printf("YES\n");else printf("NO\n");
29     }
30 }
View Code

 

B:3d

描述:code

代码:htm

 

C:

描述:

代码:

 

D:HDU4864

描述:N个机器,一个机器两个属性(时间x,等级y),M个任务(x,y),由于数据范围100*2<<1440,因此采起x大的先尽可能知足的贪心策略,而后y大的先知足

int i=0,j=0;

while(i<M,i++){
while(j<N&&P1[j].l>=P2[i].l){ vis[P1[j].t]++; j++; } for(int t=P2[i].t;t<=100;t++){ if (vis[t]){ num++; vis[t]--; score+=500*P2[i].l+2*P2[i].t; break; } } }

代码:假设如今要完成i任务,如今咱们把x大于等于i任务的机器都找出来,记录下来他们的y值,而后找到其中能作i任务的最小的y值便可,由于机器是x大的排在前面,保证了记录下来的机器的x必定大于后续的任务。

 1 #include <iostream>
 2 #include <string.h>
 3 #include <stdio.h>
 4 #include <algorithm>
 5 #define LL long long
 6 using namespace std;
 7 
 8 int N,M;
 9 struct Node{
10     LL l,t;
11     bool operator<(const Node &X)const{
12         if (l==X.l) return t>X.t;
13         else return l>X.l;
14     }
15     void print(){
16         cout<<"l="<<l<<","<<"t="<<t<<endl;
17     }
18 }P1[100100],P2[100100];
19 int vis[105];
20 int main(){
21     while(~scanf("%d%d",&N,&M)){
22         LL l,t;
23         for(int i=0;i<N;i++){
24             scanf("%I64d%I64d",&l,&t);
25             P1[i]=(Node){l,t};
26         }
27         for(int i=0;i<M;i++){
28             scanf("%I64d%I64d",&l,&t);
29             P2[i]=(Node){l,t};
30         }
31         sort(P1,P1+N);
32         sort(P2,P2+M);
33         memset(vis,0,sizeof(vis));
34         LL score=0,num=0;
35         int i=0,j=0;
36         for(;i<M;i++){
37             while(j<N&&P1[j].l>=P2[i].l){
38                 vis[P1[j].t]++;
39                 j++;
40             }
41             for(int t=P2[i].t;t<=100;t++){
42                 if (vis[t]){
43                     num++;
44                     vis[t]--;
45                     score+=500*P2[i].l+2*P2[i].t;
46                     break;
47                 }
48             }
49         }
50         printf("%I64d %I64d\n",num,score);
51     }
52     return 0;
53 }
View Code

 

E:

 

F:

 

G:

 

H:

 

I:

HDU4869

【参考:http://blog.csdn.net/libin56842/article/details/38065951的证实】

描述:桌子上有M张扑克,进行N个操做,每一个操做定义一个Xi,表示要把当点的扑克中的Xi翻一下,问最后能够有多少种状况?一开始全部牌都是朝下的(全0)。

代码:

又是一道机智题。首先,咱们知道因为对称性,假设最后有K张牌朝上, 那么,这K张牌造成的可能性为C(M,K),与翻拍的过程不要紧。

而后,由于牌只有01两种状态,因此假设sum=sigm(xi),sum为奇数,最后1的个数为奇数,不然为偶数。

            if (l1>=x) l2=l1-x;
            else if (r1>=x) {
                if (l1%2==x%2) l2=0;else l2=1;
            }else l2=x-r1;
            if (r1+x<=M) r2=r1+x;
            else if (l1+x<=M) {
                if ((l1+x)%2==M%2) r2=M;else r2=M-1;
            }else r2=2*M-(l1+x);
            l1=l2,r1=r2;
而后问题就变成了到底最后有几个1的问题,参考别人的题解,是求出最少的1的个数,和最多的1的个数,由于奇偶性肯定,从l到r每次增加1,可是,我以为还不能证实为何连续变化啊。还有就就求最小的1,由于当前01个数是惟一肯定的,因此翻的状况是惟一肯定的。
C(n,m) = n!/(m!*(n-m)!)     咱们知道N,M是很大的,组合数没法直接计算
可是咱们知道费马小定理a^(p-1)=1%p         
那么a^(p-1)/a = 1/a%p 获得 a^(p-2) =(1/a)%p
发现了吧?这样就把一个整数变成了一个分母!
那么上边的C(n,m)=n!*(1/(m!*(n-m)!)=n!=n!* (m!*(n-m)!)^(p-2)
这样就把很大的1/n!求模,变成里快速幂。
 ans+=((F[M]%Mod)*(QuickMod(F[i]*F[M-i]%Mod,Mod-2)%Mod))%Mod;
F[i]=i!%Mod
 1 #include <iostream>
 2 #include <string.h>
 3 #include <stdio.h>
 4 #include <algorithm>
 5 #define Mod 1000000009
 6 #define LL long long
 7 using namespace std;
 8 
 9 int N,M;
10 LL F[100100];
11 void builtF(){
12     F[0]=1;
13     for(int i=1;i<=100000;i++){
14         F[i]=(F[i-1]*i)%Mod;
15     }
16     return ;
17 }
18 LL QuickMod(LL a,LL p){
19     LL ans=1;
20     while(p){
21         if (p&1){
22            ans=(ans*a)%Mod;
23            p--;
24         }
25         p>>=1;
26         a=(a*a)%Mod;
27     }
28     return ans;
29 }
30 int main(){
31     builtF();
32     while(~scanf("%d%d",&N,&M)){
33         int l1=0,l2,r1=0,r2;
34         for(int i=0;i<N;i++){
35             int x;
36             scanf("%d",&x);
37             if (l1>=x) l2=l1-x;
38             else if (r1>=x) {
39                 if (l1%2==x%2) l2=0;else l2=1;
40             }else l2=x-r1;
41             if (r1+x<=M) r2=r1+x;
42             else if (l1+x<=M) {
43                 if ((l1+x)%2==M%2) r2=M;else r2=M-1;
44             }else r2=2*M-(l1+x);
45             l1=l2,r1=r2;
46         }
47         LL ans=0;
48         for(int i=l1;i<=r1;i+=2){
49             ans+=((F[M]%Mod)*(QuickMod(F[i]*F[M-i]%Mod,Mod-2)%Mod))%Mod;
50         }
51         printf("%I64d\n",ans%Mod);
52     }
53     return 0;
54 }
View Code

 

J:【参考:http://www.cnblogs.com/chanme/p/3861766.html】

描述:注册两个帐号打CF,给次选分低的帐号打,赢一次+1,输一次-2,由于分数可能下降可能升高,因此就是一种随机转移的过程,抽象成马尔可夫过程。

dp[i]=dp[i+1]*p+dp[i-2]*q+1;

dp[i]表示从i的积分到20分的指望天数。

那么从后往前推的话。dp[i]=dp[i+1]*p+dp[i-2]*q+1;

1表示本身的原本状态。

考虑边界:dp[0]=dp[1]*p+dp[0]*q+1;因此dp[0]=1/p+dp[1]

dp[1]=dp[2]*p+dp[0]*q+1;因此dp[0]=1/p+1/p^2+dp[2]

依次咱们能够顺序解出每一个dp.

由于:dp[i]=dp[i+1]*p+dp[i-2]*q+1;

dp[i-1]=dp[i]*p+dp[i-3]*q+1;

dp[i]=dp[i-1]/p-dp[i-3]*q/p+1/p=(dp[i-1]-dp[i-3]*q+1)/p

每次计算等式右边的便可。

同时,要说明的就是

dp[20]=dp[20]*p+dp[18]*q+1;

dp[19]=dp[20]*p+dp[17]*q+1;

因此dp[20]=(dp[18]*q+1)/p

最后求sum就好了

代码:

 1 #include <iostream>
 2 #include <string.h>
 3 #include <stdio.h>
 4 #include <algorithm>
 5 #define Mod 1000000009
 6 #define LL long long
 7 using namespace std;
 8 
 9 double T[30];
10 double p,ans,q;
11 int main(){
12     while(~scanf("%lf",&p)){
13         q=1-p;
14         ans=0;
15         T[0]=1/p;T[1]=T[0]/p;T[2]=T[1]/p;
16         ans+=T[0]+T[1]+T[2];
17         for(int i=3;i<20;i++){
18             T[i]=(T[i-1]-T[i-3]*q)/p;
19             ans+=T[i];
20         }
21         ans=ans*2-T[19];
22         printf("%.6lf\n",ans);
23     }
24     return 0;
25 }
View Code

 

K:

相关文章
相关标签/搜索