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:

相關文章
相關標籤/搜索