HDU 1729 Stone Game(SG函数)

来源:互联网 发布:json 汉字 编辑:程序博客网 时间:2024/05/20 18:02

Stone Game

Problem Description
This game is a two-player game and is played as follows:

1. There are n boxes; each box has its size. The box can hold up to s stones if the size is s.
2. At the beginning of the game, there are some stones in these boxes.
3. The players take turns choosing a box and put a number of stones into the box. The number mustn’t be great than the square of the number of stones before the player adds the stones. For example, the player can add 1 to 9 stones if there are 3 stones in the box. Of course, the total number of stones mustn’t be great than the size of the box.
4.Who can’t add stones any more will loss the game.

Give an Initial state of the game. You are supposed to find whether the first player will win the game if both of the players make the best strategy.
 

Input
The input file contains several test cases.
Each test case begins with an integer N, 0 < N ≤ 50, the number of the boxes.
In the next N line there are two integer si, ci (0 ≤ ci ≤ si ≤ 1,000,000) on each line, as the size of the box is si and there are ci stones in the box.
N = 0 indicates the end of input and should not be processed.
 

Output
For each test case, output the number of the case on the first line, then output “Yes” (without quotes) on the next line if the first player can win the game, otherwise output “No”.
 

Sample Input
32 03 36 226 36 30
 

Sample Output
Case 1:YesCase 2:No
 

Source
“网新恩普杯”杭州电子科技大学程序设计邀请赛

题意:两个轮流往盒子里放石子。如果盒子的容量是M,此时盒子里边有C个石子,那么这个时候最多往盒子里放1~C*C个石子,最后不能放石子的一方输。判断先手是否能赢得游戏。输入n个盒子,每个盒子容量为Mi,石子数量为Ci。

分析:如果这道题对每次放石子数量改为1~M-C,那么就是基本的Nim博弈了,然而数量现在限制成了1~C*C,那么我们开始分析先手的必赢状态。假设一个盒子的容量是Mn,假设当前的石子数量是Ti,如果此时满足Ti+Ti*Ti>=Mn(一步到位),那么先手这个时候就赢了;那么先手必输的策略呢?如果当前的石子数量是Tj,此时Tj满足Tj+Tj*Tj<Mn&&(Tj+1)+(Tj+1)*(Tj+1)>=Mn,这里先手就输了。这里不等式的意思是,在Tj的情况下,无论先手放多少个,都无法使石子数量≥Mn,由于当前至少放一个,那么当先手放了一个之后,此时的Tj+1满足(Tj+1)+(Tj+1)*(Tj+1)>=Mn,后手面对这个,后手就赢了,先手也就必输。也就是说,我们可以找出一个最大T,这个T满足T+T*T<M&&(T+1)+(T+1)*(T+1)>=Mn,如果当前的Ci大于T,对于先手来说,我肯定可以达到Mn的状态,如果Ci=T,那么先手必输了。那么当Ci<T的情况呢?我们接着分析。Ci<T,说明这个时候我是无法到达Mn状态的,然后此时的T是必输状态,如果我可以使对手面临T状态,那么我不就是必赢了?那么我应该怎么使对手面临T状态呢?(对手面临T状态,岂不是我到达T状态??QAQ~)这里有两种分析方式:第一:如果先手赢,那么先手走完后,到达Mn,后手输;第二:如果先手赢,那么先手走完后,到达T,后手输,也就是说Mn和T的状态是一样的,那么我们继续判断先手是否可以到达T,也就是说,判断在Mn里边是否存在先手到达T的情况,这样就可以在Ci<T的情况下,根据T的状态得出Mn的状态。每次的SG函数,如果先手赢,SG值就是Mn-Ci,否则为0。

代码:
#include<bits/stdc++.h>using namespace std;int get_sg(int s,int c){    int  t=sqrt(s*1.0);    while(t*t+t>=s){        t--;    }    if(c>t){        return s-c;    }    else if(c==t){        return 0;    }    else{        return get_sg(t,c);    }}int main(){    int n;    int cas=1;    while(~scanf("%d",&n),n){        int s,c;        int ans=0;        for(int i=1;i<=n;i++){            scanf("%d%d",&s,&c);            ans^=get_sg(s,c);        }        if(ans){            printf("Case %d:\nYes\n",cas++);        }        else{            printf("Case %d:\nNo\n",cas++);        }    }    return 0;}


 
原创粉丝点击