您的位置:首页 > 其它

hdu1847(求sg)

2016-05-11 23:14 323 查看
Good Luck in CET-4 Everybody!

Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 7720 Accepted Submission(s): 4964

Problem Description

大学英语四级考试就要来临了,你是不是在紧张的复习?也许紧张得连短学期的ACM都没工夫练习了,反正我知道的Kiki和Cici都是如此。当然,作为在考场浸润了十几载的当代大学生,Kiki和Cici更懂得考前的放松,所谓“张弛有道”就是这个意思。这不,Kiki和Cici在每天晚上休息之前都要玩一会儿扑克牌以放松神经。

“升级”?“双扣”?“红五”?还是“斗地主”?

当然都不是!那多俗啊~

作为计算机学院的学生,Kiki和Cici打牌的时候可没忘记专业,她们打牌的规则是这样的:

1、 总共n张牌;

2、 双方轮流抓牌;

3、 每人每次抓牌的个数只能是2的幂次(即:1,2,4,8,16…)

4、 抓完牌,胜负结果也出来了:最后抓完牌的人为胜者;

假设Kiki和Cici都是足够聪明(其实不用假设,哪有不聪明的学生~),并且每次都是Kiki先抓牌,请问谁能赢呢?

当然,打牌无论谁赢都问题不大,重要的是马上到来的CET-4能有好的状态。

Good luck in CET-4 everybody!

Input

输入数据包含多个测试用例,每个测试用例占一行,包含一个整数n(1<=n<=1000)。

Output

如果Kiki能赢的话,请输出“Kiki”,否则请输出“Cici”,每个实例的输出占一行。

Sample Input

1

3

Sample Output

Kiki

Cici

#include<cstdio>
#include<iostream>
using namespace std;
#include<algorithm>
#include<cstring>
#include<cmath>
/*
应该是个巴什博弈吧,首先3是个必败的状态,任何一个不是3的倍数的(>3)都可以经过减1或减2变成3的倍数,
而1和2都是2的倍数,所以如果把对方控制成三的倍数那么必赢,也就是说谁先抢到不是三的倍数谁赢

如果不想证直接自己写几个必胜必败状态就ok了
必赢 1 2 4 5 7 8 10 11 16 32
必输 3  6  9  12

首先,我们可以确定的是,如果谁面对的是3这个局势,那是先者是必败的,后者总可以拿最后一个石子,那3+3呢?
当然也是啦,依次类推,凡是3的倍数,皆是奇异局势
*/

//const int maxn=2049;
//int a[maxn];

//int main(){
//  int n;
//  memset(a,-1,sizeof(a));
//  for(int i=0;pow(2,i)<=1000;++i){
//      a[(int)pow(2,i)]=1;
//  }
//  for(int i=1;i<=1000;++i){
//      if(a[i]!=-1)continue;
//      bool ans=false;
//      for(int j=0;pow(2,j)<=1000;++j){
//          if(i-(int)(pow(2,j))>0){
//              if(!a[i-(int)(pow(2,j))]){
//                  ans=true;
//                  break;
//              }
//          }
//      }
//      a[i]=ans;
//  }
//  while(cin>>n){
////        if(n%3)printf("Kiki\n");
////        else printf("Cici\n");
//      //求 SG 值
//      if(a
)printf("Kiki\n");
//      else printf("Cici\n");
//  }
//  return 0;
//}
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

const int maxn = 1000 + 10;
int arr[11], sg[maxn];

void pre() { //把1000以内的所有的可能一次拿的牌都算出来!
arr[0] = 1;
for(int i=1; i<=10; ++i)
arr[i] = arr[i-1]*2;
}

/*
SG值:一个点的SG值就是一个不等于它的后继点的SG的且大于等于零的最小整数。//同mex()函数
简单点来讲就是当前状态离最近一个必败点的距离。距离为0就是必败点

SG(x)=mex(S)
S是x的后继状态的SG函数值集合
mex(S)表示不在S内的最小非负整数
*/
int mex(int x) { //这是求解该点的sg值的算法函数(采用记忆化搜索)
if(sg[x]!=-1) return sg[x];
bool vis[maxn];
memset(vis, false, sizeof(vis) );
for(int i=0; i<10; ++i) {
int temp = x - arr[i];
if(temp<0) break;
sg[temp] = mex(temp);
vis[sg[temp]] = true;
}

for(int i=0;i<=1000; ++i) {
if(!vis[i]) {
sg[x] = i;
break;
}
}
return sg[x];
}
int main() {
int n;
pre();
memset(sg, -1, sizeof sg );
while(scanf("%d", &n)!=EOF) {

if(mex(n)) printf("Kiki\n");
else printf("Cici\n");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: