1. 程式人生 > >hdu 1729 Stone Game

hdu 1729 Stone Game

fin -- stream mes else targe tps gpo 遞歸

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:\n",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"); } }

hdu 1729 Stone Game