P4018 Roy&October之取石子
题目背景
Roy和October两人在玩一个取石子的游戏。
题目描述
游戏规则是这样的:共有n个石子,两人每次都只能取p^kp
k
个(p为质数,k为自然数,且p^kp
k
小于等于当前剩余石子数),谁取走最后一个石子,谁就赢了。
现在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。
(改编题)
看似这个题很复杂的样子,每一次可以在数里取走\(为整数且p^k(k为整数,且\ge 0)\)
那这一看就是博弈论吧。于是考虑所有的必胜态。
显然,当前这个数为\(为质数p(p为质数)\)的次幂都可以必胜。
那根据博弈观点,所有的通过一次到达上面状态的都是必败态。
于是有下面的办法
pri[maxn]//全为质数
//cnt为选出的质数个数
dp[1]=1;
for(int k=2;k<=max;k++)
for(int i=1;i<cnt;i++)
for(int j=1;j;j*=cnt[i])
if(!dp[k-j])dp[k]=1;
这样就可以找出所有的数了。
太慢了有木有。。。
于是打表发现所有的必败态都是6的倍数
于是
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
inline int read(){
int an=0;
char ch=getchar();
while(ch<'0'||ch>'9'){ch=getchar();}
while('0'<=ch&&ch<='9'){an=an*10+(ch^48);ch=getchar();}
return an;
}
int n;
int main(){
ios::sync_with_stdio(0);
n=read();
for(;n;n--){
int x=read();
if(x%6)cout<<"October wins!\n";
else cout<<"Roy wins!\n";
}
return 0;
}