题目大意:两个人取n张牌,每次只能取1,2,4等2的幂次张,取完最后一张的获胜。问先手必胜吗?
关键思想:有求SG值的方法,或者找规律的方法,仅贴代码不做讲述,到处都有。了解基础博弈论的话很容易理解。
代码如下:
SG值——
#include <cstdio> #include <cstring> #include <iostream> using namespace std; int sg[1005]; int vis[1005]; int main() { int n; sg[1] = 1; sg[2] = 2; for(int i = 3; i <= 1000; i ++){ memset(vis, 0, sizeof(vis)); for(int j = 1; j <= i; j *= 2){ vis[sg[i-j]] = 1; // i-j为后继状态,vis[sg[i-j]]收录S集合 } for(int j = 0; ; j ++){ if(vis[j] == 0){ sg[i] = j; break; // 求没有出现在集合中的非负最小值 } } //cout << sg[i] << endl; } // for(int i = 1; i <= 100; i ++) // cout << sg[i] << endl; while(scanf("%d", &n) != EOF){ if(sg[n] == 0) printf("Cici\n"); else printf("Kiki\n"); } return 0; }
总结规律——容易发现3是必败点,而任何一个“非3的倍数”数-1或者-2都能成为3的倍数,所以3的倍数其实都是必败点。其他点则为必胜点。(先手)
#include <iostream> using namespace std; int main(){ int n; while(cin>>n){ if(n%3==0)cout<<"Cici"<<endl; else cout<<"Kiki"<<endl; } return 0; }