hdu1729取石子游戏 sg!!

来源:互联网 发布:360手机数据恢复免费版 编辑:程序博客网 时间:2024/05/17 04:25

题目大意:(取石子游戏)有n个箱子,体积为Si,当前箱子里的石子数为Ci。两个人轮流往箱子里放石子,而且每一次放是数量都有限制,不能超过当前箱子内石子数的平方。例如箱子里有3颗石子,那么下一个人就可以放1~9颗石子,直到箱子被装满。当有一方放不下石子时游戏结束,最后放不下石子的人输。

别人的题解http://qianmacao.blog.163.com/blog/static/2033971802012343334856/

思路:这题明显的sg函数。可惜我纠结了半天没想起思路来。设当前的箱子容量为si,求出一个t满足:t + t * t < si,若是当前箱子里有ci颗石头,         1、ci > t 则必胜;         2、ci == t 则必败;         3、ci < t不可立即断定,将t作为si递归调用函数。当满足ci > t时,return si - ci 作为当前状况的sg值。因为:当ci在si点时,为有向图的端点,出度为0,也就是必败点,所以sg值为0;当ci 位于si - 1时,ci的端点可能的sg值构成的凑集为{0},所以当前sg值 为1;当ci 位于si - 2 时,ci的端点可能的sg值构成的凑集为{01},所以当前的sg值为2;可得,ci地点地位的sg值为si - ci;

首先 我们知道S是必败点。
然后找到最大的t使 t + t * t < si
则 区间 t+1 — S-1 是必胜点,因为可以一步到S
如果
①C > t 那么C是必胜点
②C = t 必败
③C < t 未知,将t作为S递归求解(看谁先到t)

当满足c > 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 <bits/stdc++.h>using namespace std;int mes(int x, int n){  int t = (int)sqrt(n * 1.0);  while (t + t * t >= n) t--;  if (t < x) return n - x;  else return mes(x, t);}int main(){  int N, a, b, icase = 1;  while (cin >> N && N) {    int ans = 0;    while (N--) {      scanf("%d%d", &a, &b);      if (b == 0 || a == 0 || b == a) continue;      ans ^= mes(b, a);    }    if (ans == 0)      printf("Case %d:\nNo\n", icase++ );    else printf("Case %d:\nYes\n", icase++ );  }}
0 0
原创粉丝点击