HDU 1729 Stone Game (sg函数)

20 篇文章 1 订阅



Stone Game

Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)
Total Submission(s): 3287    Accepted Submission(s): 1048


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
  
  
3 2 0 3 3 6 2 2 6 3 6 3 0
 

Sample Output
  
  
Case 1: Yes Case 2: No
 

Source
 

Recommend
lcy

题意:

n个瓶子,每个瓶子里面有一些石头,每次向瓶子里面放石头的数量不能超过瓶子中已经存在的石头数量的平方。

很容易看出是“组合游戏和”,因此只需要求出每个瓶子的sg函数值,然后求Nim和即可。

思路:

寻找必败态:

设t,t*t +t < s 而且使 t 尽量的大,则(t+1)*(t+1) +(t+1) >= s,因此

1. c > t 则当前状态是必胜态,因为c*c+c >= s成立

2. c == t 则当前状态为必败态,因为最多放c*c个石头,瓶子未满,对手必胜,至少放1个石头,则对手也是必胜。

3. c < t 当前状态无法确定,而在瓶子中已经有c个石头的前提下,容量为 s 和容量为 t 的状态是等价的,如果(t, c)是必败态,则(s, c)也是必败态。

当满足ci > t时,return si - ci 作为当前状态的sg值。因为:

如图:

当ci在si点时,为有向图的端点,出度为0,也就是必败点,所以sg值为0;

当ci 位于si - 1时,ci的端点可能的sg值构成的集合为{0},所以当前sg值 为1;

当ci 位于si - 2 时,ci的端点可能的sg值构成的集合为{0, 1},所以当前的sg值为2;

可得,ci所在位置的sg值为si - ci;

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
int sg(int c, int s)
{
    int t = sqrt(s);
    while(t+t*t >= s) t--;
    if(c > t) return s - c;
    else sg(c, t);
}
int main()
{
    int n, c, s, ca = 0, ans = 0;
    while(~scanf("%d", &n), n)
    {
        printf("Case %d:\n", ++ca);
        ans = 0;
        for(int i = 1; i <= n; i++)
        {
            scanf("%d%d", &s, &c);
            ans ^= sg(c, s);
        }
        if(ans) printf("Yes\n");
        else printf("No\n");
    }
    return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值