题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=1847
/*步骤1:将所有终结位置标记为必败点(P点);
步骤2: 将所有一步操作能进入必败点(P点)的位置标记为必胜点(N点)
步骤3:如果从某个点开始的所有一步操作都只能进入必胜点(N点) ,则将该点标记为必败点(P点) ;
步骤4: 如果在步骤3未能找到新的必败(P点),则算法终止;否则,返回到步骤2。
*/
/*1.能一步走到必败点的都是必胜点
##2.无论怎么走都只能走到必胜点的是必败点
##
##思路:
##1.数组judge 0表示必败,1表示必胜 judge[i] 表示i所处
##的局势
##2.下标 1,2,4,8,16....这些2的次幂显然是必胜点
##3.选取必败点 假设该必败点下标为k 则 k+1,k+2,k+4,k+8,k+16....
##这些能一步走到必败点k的下标均表示必胜点
##
关键 :怎么选取必败点?
->>>未曾出现过的最小自然数 即是 必败点
为什么?
->>>>
judge[1,2,4,8,16...]=1;
i=3时 发现judge[i]=0 又发现i=3时 先手无论是走1或者2都会输 因此是必败点
judge[i+1,i+2,i+4,i+8,i+16...]=1;
i=6时 发现judge[i]=0 又发现i=6时 无论是走1,2,4那个都会输 因此事必败点
judge[i+1,i+2,i+4,i+8,i+16...]=1;
.....
*/
#include<cstdio>
const int N=1001;
bool judge[N];
int dec[10];
void Initial()
{
for(int i=0;i<10;++i){
judge[1<<i]=true;
dec[i]=1<<i;
} //置一表示为必胜点
for(int i=0;i<N;++i){
if(!judge[i]){//找到最小的自然数根据性质知是必败点
for(int j=0;j<10;++j)if(i+dec[j]<N){
judge[i+dec[j]]=true;//能一步走到必败点的都是必胜点
}else break;
}
}
}
int main()
{
int n;
Initial();
while(~scanf("%d",&n)){
if(judge[n]) puts("Kiki");
else puts("Cici");
}
}