HDU 1729 Stone Game【SG函数】

以下转载至:长春理工大学赵小舟博弈论ppt

题目大意:

1、有n个盒子,每个盒子都有它的容量s

2、在游戏开始时,每个盒子里都有一些石子

3、双方轮流进行游戏,向一个盒子投入n个石子,其中n不能大于当前盒子中石子数量的平方,投入后盒中石子数不能超过其容量

例:如果现在盒中有3个石子,则可以向里投1-9个

4、谁不能向任何盒中投石子为负

给出n个盒子的初态, 问在双方均为最优策略时先手者是否能取胜

思路:

s=20的情况(k代表题目中的c)

规律:k(k+1)<s时k的最大值为sg=0的一点,其后的sg值从s-k-1开始递减。

二分寻找k的最大值,并将其赋给s,与盒中初始石子数量比较,若k大,可直接得出sg值,若小,将k赋值给s,继续寻找。

其实当寻找更大的s的sg值情况时,可以发现,从k-1~2的sg指从1依次递增。

#include<stdio.h>
#include<string.h>
#include<math.h>
int SG(int s,int c){
    if(!s||!c)    return 0;
    while(1){
        int l=0,r=sqrt(s),k;
        while(l<=r){
            k=(l+r)>>1;
            if(k*(k+1)<s)
                l=k+1;
            else
                r=k-1;
        }
        k=r;
        if(k==c)        return 0;
        else if(k<c)    return s-c;
        s=k;
    }
}
int main(){
    int n,s,c,ans,cas=0;
    while(~scanf("%d",&n)&&n){
        ans=0;
        while(n--){
            scanf("%d%d",&s,&c);
            ans^=SG(s,c);
        }
        printf("Case %d:
",++cas);
        if(ans)    puts("Yes");
        else    puts("No");
    }
    return 0;
} 
原文地址:https://www.cnblogs.com/L-King/p/5765278.html