#include<stdio.h>
#include<iostream>
#include<string.h>
#include<string>
#include<ctype.h>
#include<math.h>
#include<set>
#include<map>
#include<vector>
#include<queue>
#include<bitset>
#include<algorithm>
#include<time.h>
using namespace std;
void fre(){freopen("c://test//input.in","r",stdin);freopen("c://test//output.out","w",stdout);}
#define MS(x,y) memset(x,y,sizeof(x))
#define MC(x,y) memcpy(x,y,sizeof(x))
#define MP(x,y) make_pair(x,y)
#define ls o<<1
#define rs o<<1|1
typedef long long LL;
typedef unsigned long long UL;
typedef unsigned int UI;
template <class T1,class T2>inline void gmax(T1 &a,T2 b){if(b>a)a=b;}
template <class T1,class T2>inline void gmin(T1 &a,T2 b){if(b<a)a=b;}
const int N=0,M=0,Z=1e9+7,ms63=1061109567;
int n,k,x;
int odd(int x)
{
if(x==0)return 0;
if(x==1)return 1;
if(x==2)return 0;
if(x>=5&&(x&1))return 0;
int two=0;while(x%2==0){x/=2;++two;}
if(x==3)return two&1?2:1;
else return two&1?1:2;
}
int even(int x)
{
if(x<=2)return x;
else return (x&1)?0:1;
}
void oddtable()
{
int sg[105];
bool e[105];
sg[0]=0;
for(int i=1;i<=100;++i)
{
MS(e,1);
e[sg[i-1]]=0;
if(i%2==0)e[sg[i/2]]=0;
int j;for(j=0;;++j)if(e[j])break;
sg[i]=j;
}
for(int i=1;i<=100;++i)
{
printf("%d %d %d\n",i,sg[i],odd(i));
}
}
int main()
{
//oddtable();
while(~scanf("%d%d",&n,&k))
{
int ans=0;
for(int i=1;i<=n;++i)
{
scanf("%d",&x);
if(k&1)ans^=odd(x);
else ans^=even(x);
}
puts(ans?"Kevin":"Nicky");
}
return 0;
}
/*
【题意】
有n(1<=n<=1e5)个数值a[],每个数值的范围都在[1,1e9]范围。
Kevin先手,Nicky后手。当一个人再也无法操作的时候认为这个人败。
操作有两种——
1,选择一个数,做-1操作,数如果变成0,就移除。
2,选择一个偶数,设这个偶数为2x,我们把这个数移除,并替换成k个x
【类型】
博弈
【分析】
好久没有遇到正儿八经的博弈题了,遇到之后发现自己什么都不会TwT。
那么——这道题要如何做呢?
首先,要指出我做博弈题的一个傻叉点。
我思考的时候,每个数,要不就是必胜态,要不就是必败态。
我忽略了——事实上,每个数,是可能对应着一个SG值的。
我们最后的胜负,不是由于必胜态或必败态叠加决定。
而是经过若干SG值的异或结果决定。
SG值表示,对于一个状态,如果它的前驱节点有,有某个SG值,这个状态就不能取这个SG值。
对于这个状态,从0开始,它可以取的最小的数字,就作为它的SG值。
如果SG值的异或和为0,那么先手必败;否则先手必胜。
然而,我们要如何算出每个数的SG值呢?
SG值一般的计算方法可以是DP打表,然而这道题的数值范围巨大, 显然没法打表,我们要更一针见血一些。
首先,我们可以显然得到一个结论,k影响我们答案的,实际只是其奇偶性。
因为,如果k为偶数,那么对于操作2,我们会分裂出偶数个f(x),而这偶数个f(x)的异或和显然是0,这个点就可以达到一个SG值为0的前驱
所以,在k为偶数的情况下,我们可以算出——
f[0]=0;
f[1]=1;
f[2]=2;
f[3]=0;
f[4]=1;
接下来呢?
f[5]=0;
f[6]=1;
f[7]=0;
f[8]=1;
显然奇数只能达到偶数前驱,偶数前驱的SG值都为0,所以这些奇数的SG值都为1。
显然偶数能达到奇数前驱,奇数前驱的SG值都为0,而它能分裂到达的SG值也为0,所以偶数的SG值也都为1.
于是我们就求出所有点的SG值啦。
再讨论,如果k为奇数,那么对于操作2,我们会分裂出奇数个f(x),而这奇数个f(x)的异或值相消,就只剩下了一个f(x)
所以,在k为奇数的情况下,我们可以算出——
sg[0]=0;
sg[1]=1;
sg[2]=0;
sg[3]=1;
sg[4]=2;
接下来呢?
发现情况有些复杂,于是我们可以打个表——
sg[5]=0;
sg[6]=2;
sg[7]=0;
sg[8]=1;
sg[9]=0;
sg[10]=1;
sg[11]=0;
sg[12]=1;
sg[13]=0;
sg[14]=1;
sg[15]=0;
sg[16]=2;
sg[17]=0;
sg[18]=1;
sg[19]=0;
sg[20]=2;
int odd(int x)
{
if(x==0)return 0;
if(x==1)return 1;
if(x==2)return 0;
if(x>=5&&(x&1))return 0;
int two=0;while(x%2==0){x/=2;++two;}
if(x==3)return two&1?2:1;
else return two&1?1:2;
}
我们会发现,除了1和3的SG值为1,其他奇数的SG值全是0。
偶数(设这个偶数为X为2x)的SG值呢?首先不会是0.然后不停地迭代下去——
如果SG[x]==1,那么SG[2x]就是2
如果SG[x]==2,那么SG[2x]就是1
于是,我们要看X中有多少个2,设X=2^k*x,
sg[1]=1;
sg[3]=1;
sg[other odd]=0;
先讨论,如果x>=5且x为奇数,即sg[other odd]==0的情况——
如果k为奇数,那么sg[X]=1;
如果k为偶数,那么sg[X]=2;
再讨论,如果x==3,即sg[3]=1的情况,
如果k为奇数,那么sg[X]=2;
如果k为偶数,那么sg[X]=1;
再讨论,如果x==1,即sg[1]==1的情况
sg[1]要特判为1,sg[2]要特判为0,其他情况,与x>=5且x为奇数的情况相同。
于是,这些写下之后这样这道题就做完了!
【时间复杂度&&优化】
if(x&1)—— O(nlogMAX)
else —— O(n)
【数据】
1 3
4
*/
【Codeforces Round 334 (Div 2)E】【博弈-SG函数】Lieges of Legendre n个数 每次取数-1或者变2x为k个x的博弈
最新推荐文章于 2019-07-17 21:02:00 发布