hdu1847(SG函數)

Good Luck in CET-4 Everybody!

大學英語四級考試就要來臨了,你是不是在緊張的複習?也許緊張得連短學期的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!

題解

可以說是SG函數的模板題了,首先求出所有2的冪作爲取數數組,然後依次求出每個數的SG函數值,若SG函數值爲0,說明此狀態是必敗態,若不爲0,則代表着第一次應該取的數字,先手的人取SG函數值個時,就讓後手的人陷入必敗態

代碼

#include<iostream>
#include<cstring>
using namespace std;
const int Maxm=1010,Maxn=10;
int f[15],sg[Maxm];
bool Hash[Maxm];
void Getsg()
{
	f[0]=1;
	for(int i=1;i<=10;i++){
		f[i]=f[i-1]<<1;
	}
	for(int i=1;i<Maxm;i++){
		//cout<<"i:"<<i<<endl;
		memset(Hash,false,sizeof(Hash));
		for(int j=0;j<=10&&f[j]<=i;j++){
			Hash[sg[i-f[j]]]=true;
			//cout<<sg[i-f[j]]<<' ';
		}
		//cout<<endl;
		for(int j=0;j<=i;j++){
			if(!Hash[j]){
				sg[i]=j;
				//cout<<j<<endl;
				break;
			}
		}
	}
}
int main()
{
	Getsg();
	int m;
	while(scanf("%d",&m)==1){
		if(sg[m]!=0){
			cout<<"Kiki"<<endl;
		}
		else{
			cout<<"Cici"<<endl;
		}
	}
} 
發佈了63 篇原創文章 · 獲贊 3 · 訪問量 4630
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章