Evanyou Blog 彩带

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$的倍数就好了。

代码:

 

#include<bits/stdc++.h>
#define il inline
#define ll long long
#define For(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
#define Bor(i,a,b) for(int (i)=(b);(i)>=(a);(i)--)
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)>(b)?(b):(a))
using namespace std;
int T,n;

il int gi(){
    int a=0;char x=getchar();bool f=0;
    while((x<'0'||x>'9')&&x!='-')x=getchar();
    if(x=='-')x=getchar(),f=1;
    while(x>='0'&&x<='9')a=(a<<3)+(a<<1)+x-48,x=getchar();
    return f?-a:a;
}

int main(){
    T=gi();
    while(T--){
        n=gi();
        if(n%6==0)puts("Roy wins!");
        else puts("October wins!");
    }
    return 0;
}

 

posted @ 2018-06-27 20:01  five20  阅读(221)  评论(0编辑  收藏  举报
Live2D