int sg[MAXN];
int get_sg(int x, int n){
if(sg[x]!=-1)
return sg[x];
bool vis[105]={0};
for(int i=0;i<n;++i){
int tmp = a[i]; //tmp是转移的下一个状态的步数
if(x >= tmp){
sg[x - tmp] = get_sg(x - tmp, n);
vis[sg[x - tmp]] = 1;
}
}
for(int i=0;;++i)
if(!vis[i]) return sg[x]=i;
}
void init(){
memset(sg,-1,sizeof(sg));
sg[0]=0;
}
void get_sg(){
sg[0]=0;
for(int i=1;i<N;++i){
set<int> s;
for(int j=0;j<10;++j){
int tmp=(1<<j); //tmp是转移的下一个状态的步数
if(i >= tmp)
s.insert(sg[i - tmp]);
}
int g=0;
while(s.count(g)!=0) ++g;
sg[i]=g;
}
}
/*hdu 1847
题意:
1. 总共n张牌;
2. 双方轮流抓牌;
3. 每人每次抓牌的个数只能是2的幂次(即:1,2,4,8,16…)
4. 抓完牌,胜负结果也出来了:最后抓完牌的人为胜者;
假设Kiki和Cici都是足够聪明,并且每次都是Kiki先抓牌,请问谁能赢呢?
限制:
1 <= n <= 1000
思路:
sg函数
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<set>
using namespace std;
const int N=1005;
const int M=105;
int sg[N];
/*int get_sg(int x){
if(sg[x]!=-1)
return sg[x];
bool vis[M];
memset(vis,0,sizeof(vis));
for(int i=0;i<10;++i){
int tmp = (1<<i);
if(x >= tmp){
sg[x - tmp] = get_sg(x - tmp);
vis[sg[x - tmp]] = 1;
}
}
for(int i=0;;++i)
if(!vis[i]) return i;
}
void get_sg(){
sg[0]=0;
for(int i=1;i<=1000;++i){
sg[i]=get_sg(i);
}
}*/
void get_sg(){
sg[0]=0;
for(int i=1;i<N;++i){
set<int> s;
for(int j=0;j<10;++j){
int tmp=(1<<j);
if(i >= tmp)
s.insert(sg[i - tmp]);
}
int g=0;
while(s.count(g)!=0) ++g;
sg[i]=g;
}
}
void init(){
memset(sg,-1,sizeof(sg));
}
int main(){
init();
get_sg();
int n;
while(scanf("%d",&n)!=EOF){
if(sg[n]==0)
puts("Cici");
else
puts("Kiki");
}
return 0;
}版权声明:本文为博主原创文章,未经博主允许不得转载。
原文:http://blog.csdn.net/whai362/article/details/46834683