P4018 Roy&October之取石子
Posted five20
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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!"。
输入输出样例
说明
对于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 imes 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之取石子的主要内容,如果未能解决你的问题,请参考以下文章