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 }
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 }
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個數是惟一肯定的,因此翻的狀況是惟一肯定的。
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 }
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 }
K: