hdu 1729 Stone Game

Stone Game

 HDU - 1729 

题意:
给定n个箱子,每个箱子的容量为si,每个箱子里最初有ci个石子,每次放入石子不能超过放入前的石子数的平方,谁无法继续放入石子就算输。
 
/*
    这是个SG函数的基础题?并不是的吧。。
    求一个t使t+t*t=si,那么
    1.当ci>t时,是必胜态,可以一次性放满箱子,即(si,si)。
    2.当ci==t时,即便只放一个,下一个状态t+1+(t+1)*(t+1)一定能放满箱子必胜,所以ci==t这个状态必败。
    3.当ci=si-t,同样的方法判断必胜必败,这样就可以通过递归求解sg值。
     
    求sg:要得到sg需要对他的子集做mex{}运算,求出不属于该集合的最小非负整数。
    在ci>t时满足
    对于ci==si这个点,ci在有向图中没有出度(必败),因此返回si-ci=0,;
    在ci==si-1时,它能到达的只有si点,sg[ci]={sg[si]=0},所以sg[ci]=1.
    在ci==si-2时,他能到达的点有si-1,si,所以sg[ci]={sg[si-1]=1,sg[si]=0},所以sg[ci]=2.
    因此在ci>t时返回si-ci
    在ci==t是是必败,可直接返回0,也可以不做判断直接进入下一轮递归。
*/
#include<iostream>
#include<cstdio>
#include<cmath>
#define maxn 51
using namespace std;
int n;
int getSG(int s,int c){
    int t=sqrt(s);
    while(t*t+t>=s)t--;
    if(c>t)return s-c;
    if(c==t)return 0;
    return getSG(t,c);
}
int main(){
    int cas=0;
    while(scanf("%d",&n)){
        cas++;
        if(n==0)return 0;
        printf("Case %d:
",cas);
        int ans=0,s,c;
        for(int i=1;i<=n;i++){
            scanf("%d%d",&s,&c);
            ans^=getSG(s,c);
        }
        if(ans)puts("Yes");
        else puts("No");
    }
}
原文地址:https://www.cnblogs.com/thmyl/p/8137585.html