Description
有 n n 堆石子,第堆有 ai a i 个石子,每轮可以有两种操作,第一种是选一堆非空石子取走一个,第二种是对于一个有 2x 2 x 个石子的偶数堆,将其分成 k k 个个石子的堆,问谁必胜
Input
第一行两个整数 n,k n , k ,之后输入 n n 个整数
Output
输出胜者
Sample Input
2 1
3 4
Sample Output
Kevin
Solution
组合游戏,记 sg[x] s g [ x ] 为 x x 个石子的堆的值, A A 为若干非负整数的集合,表示不是 A A 集合的自然数最小值
若为偶数,那么有 2x 2 x 个石子的偶数堆用第二种操作会变成偶数个 x x 个石子的堆,这种后继状态的值为偶数个 sg[x] s g [ x ] 异或,即为 0 0 ,进而有,暴力计算得 sg[0,1,2,3,4]=0,1,2,0,1 s g [ 0 , 1 , 2 , 3 , 4 ] = 0 , 1 , 2 , 0 , 1 ,用数学归纳法验证, n≥2 n ≥ 2 时, sg[2n−1]=0,sg[2n]=1 s g [ 2 n − 1 ] = 0 , s g [ 2 n ] = 1
k=2 k = 2 时显然成立结论成立, k=n k = n 时若成立 sg[2k−1]=0,sg[2k]=1 s g [ 2 k − 1 ] = 0 , s g [ 2 k ] = 1 ,那么 k=n+1 k = n + 1 时:
sg[2k+1]=mex(sg[2k])=0 s g [ 2 k + 1 ] = m e x ( s g [ 2 k ] ) = 0 , sg[2k+2]=mex(0,sg[2k+1])=1 s g [ 2 k + 2 ] = m e x ( 0 , s g [ 2 k + 1 ] ) = 1
故结论成立,进而得到了任意 n n 的值
若 k k 为奇数,那么有,暴力计算得 sg[0,1,2,3,4,5]=0,1,0,1,2,0 s g [ 0 , 1 , 2 , 3 , 4 , 5 ] = 0 , 1 , 0 , 1 , 2 , 0 ,用数学归纳法验证, n≥2 n ≥ 2 时, sg[2n]>0,sg[2n+1]=0 s g [ 2 n ] > 0 , s g [ 2 n + 1 ] = 0
k=2 k = 2 时结论显然成立, k=n k = n 时若成立 sg[2k]>0,sg[2k+1]=0 s g [ 2 k ] > 0 , s g [ 2 k + 1 ] = 0 ,那么 k=n+1 k = n + 1 时:
sg[2k+2]=mex(sg[2k+1],sg[k+1])>0(sg[2k+1]=0) s g [ 2 k + 2 ] = m e x ( s g [ 2 k + 1 ] , s g [ k + 1 ] ) > 0 ( s g [ 2 k + 1 ] = 0 ) , sg[2k+3]=mex(sg[2k+2])=0 s g [ 2 k + 3 ] = m e x ( s g [ 2 k + 2 ] ) = 0
故结论成立,进而得到所有奇数的 sg s g 值,对于所有的 sg[2x] s g [ 2 x ] ,递归求出 sg[x] s g [ x ] 即可,时间复杂度 O(log2x) O ( l o g 2 x )
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;
}