Description
有nn堆石子,第堆有aiai个石子,每轮可以有两种操作,第一种是选一堆非空石子取走一个,第二种是对于一个有2x2x个石子的偶数堆,将其分成kk个个石子的堆,问谁必胜
Input
第一行两个整数n,kn,k,之后输入nn个整数
Output
输出胜者
Sample Input
2 1
3 4
Sample Output
Kevin
Solution
组合游戏,记sg[x]sg[x]为xx个石子的堆的值,AA为若干非负整数的集合,表示不是AA集合的自然数最小值
若为偶数,那么有2x2x个石子的偶数堆用第二种操作会变成偶数个xx个石子的堆,这种后继状态的值为偶数个sg[x]sg[x]异或,即为00,进而有,暴力计算得sg[0,1,2,3,4]=0,1,2,0,1sg[0,1,2,3,4]=0,1,2,0,1,用数学归纳法验证,n≥2n≥2时,sg[2n−1]=0,sg[2n]=1sg[2n−1]=0,sg[2n]=1
k=2k=2时显然成立结论成立,k=nk=n时若成立sg[2k−1]=0,sg[2k]=1sg[2k−1]=0,sg[2k]=1,那么k=n+1k=n+1时:
sg[2k+1]=mex(sg[2k])=0sg[2k+1]=mex(sg[2k])=0,sg[2k+2]=mex(0,sg[2k+1])=1sg[2k+2]=mex(0,sg[2k+1])=1
故结论成立,进而得到了任意nn的值
若kk为奇数,那么有,暴力计算得sg[0,1,2,3,4,5]=0,1,0,1,2,0sg[0,1,2,3,4,5]=0,1,0,1,2,0,用数学归纳法验证,n≥2n≥2时,sg[2n]>0,sg[2n+1]=0sg[2n]>0,sg[2n+1]=0
k=2k=2时结论显然成立,k=nk=n时若成立sg[2k]>0,sg[2k+1]=0sg[2k]>0,sg[2k+1]=0,那么k=n+1k=n+1时:
sg[2k+2]=mex(sg[2k+1],sg[k+1])>0(sg[2k+1]=0)sg[2k+2]=mex(sg[2k+1],sg[k+1])>0(sg[2k+1]=0),sg[2k+3]=mex(sg[2k+2])=0sg[2k+3]=mex(sg[2k+2])=0
故结论成立,进而得到所有奇数的sgsg值,对于所有的sg[2x]sg[2x],递归求出sg[x]sg[x]即可,时间复杂度O(log2x)O(log2x)
Code
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<ctime>
using namespace std;
typedef long long ll;
#define INF 0x3f3f3f3f
#define maxn 111111
int n,k,a,f[5];
map<int,int>sg;
int solve(int a)
{
if(a<5)return f[a];
if(a%2)return 0;
return solve(a/2)==1?2:1;
}
int main()
{
f[0]=0,f[1]=1,f[2]=0,f[3]=1,f[4]=2;
scanf("%d%d",&n,&k);
int ans=0;
if(k%2==0)
{
for(int i=1;i<=n;i++)
{
scanf("%d",&a);
if(a==2)ans^=2;
else if(a==1||a>2&&a%2==0)ans^=1;
}
}
else
{
for(int i=1;i<=n;i++)
{
scanf("%d",&a);
ans^=solve(a);
}
}
printf("%s\n",ans?"Kevin":"Nicky");
return 0;
}