P4018 Roy&October之取石子
題目背景
Roy和October兩人在玩一個取石子的遊戲。
題目描述
遊戲規則是這樣的:共有n個石子,兩人每次都只能取 p^kpk 個(p為質數,k為自然數,且 p^kpk 小於等於當前剩余石子數),誰取走最後一個石子,誰就贏了。
現在October先取,問她有沒有必勝策略。
若她有必勝策略,輸出一行"October wins!";否則輸出一行"Roy wins!"。
輸入輸出格式
輸入格式:
第一行一個正整數T,表示測試點組數。
第2行~第(T+1)行,一行一個正整數n,表示石子個數。
輸出格式:
T行,每行分別為"October wins!"或"Roy wins!"。
輸入輸出樣例
輸入樣例#1:
3
4
9
14
輸出樣例#1: October wins!
October wins!
October wins!
說明
對於30%的數據,1<=n<=30;
對於60%的數據,1<=n<=1,000,000;
對於100%的數據,1<=n<=50,000,000,1<=T<=100,000。
(改編題)
Solution:
本題比較水。
首先,不難發現$1,2,3,4,5$都是先手贏,到了$6$時就後手贏了,而對於大於$6$小於$12$的數,都能取$[1,5]$中的某個數,使其變為$6$,而到了$12$又是後手贏…
直接告訴我們,$6$的倍數是先手必輸狀態,其余為先手必勝狀態。
首先,$6$的倍數一定不是某一質數的冪(這是顯然的,因為$6=2\times 3$,所以$6$的倍數至少含兩個質因子),所以$6$的倍數一定不能被一次取完。
然後無論$6$的倍數怎麽取,都至少取走一個非$6$的倍數的數,那麽剩下的數必定為非$6$的倍數的數,我們只要從$[1,5]$中取某個值就能使得其又變為$6$的倍數。
最後一定能夠回到值為$6$且後手取的情況,此時後手無論取何值,都是輸。
所以只需判斷一下是否是$6$的倍數就好了。
代碼:
1 #include<bits/stdc++.h> 2#define il inline 3 #define ll long long 4 #define For(i,a,b) for(int (i)=(a);(i)<=(b);(i)++) 5 #define Bor(i,a,b) for(int (i)=(b);(i)>=(a);(i)--) 6 #define Max(a,b) ((a)>(b)?(a):(b)) 7 #define Min(a,b) ((a)>(b)?(b):(a)) 8 using namespace std; 9 int T,n; 10 11 il int gi(){ 12 int a=0;char x=getchar();bool f=0; 13 while((x<‘0‘||x>‘9‘)&&x!=‘-‘)x=getchar(); 14 if(x==‘-‘)x=getchar(),f=1; 15 while(x>=‘0‘&&x<=‘9‘)a=(a<<3)+(a<<1)+x-48,x=getchar(); 16 return f?-a:a; 17 } 18 19 int main(){ 20 T=gi(); 21 while(T--){ 22 n=gi(); 23 if(n%6==0)puts("Roy wins!"); 24 else puts("October wins!"); 25 } 26 return 0; 27 }
P4018 Roy&October之取石子