码迷,mamicode.com
首页 > 其他好文 > 详细

hdoj 1729 Stone Games(SG函数)

时间:2015-08-11 21:20:41      阅读:105      评论:0      收藏:0      [点我收藏+]

标签:

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1729

看了题目感觉像Nim,但是有范围限制,有点不知道SG函数该怎么写

看了题解,最后才明白该怎么去理解 。

首先进行对s和c进行分类,

1、c = 0 的时候,无论怎样都填不满,直接跳过;

2、c = s 的时候,先手必败,即是P态;

3、c < s 的时候,可以分为两种情况:

1)c^2 + c < s 的时候,递归

2)c^2 + c > s 的时候,先手必胜,即N态

1 int mex(int s, int c){
2     if( c == 0 || s == c)
3         return 0;
4     int q = sqrt(s);
5     while( q+q*q >= s)
6         q--;//最大的不能一次填满的数
7     if(c > q) return s-c;
8     else return mex(q,c);
9 }

主要的理解难点就是 mex(s,c)和mex(k,c)为什么是等价的,个人是这么理解的,

当跑到第一个q+q*q<s的时候,如果c>q,那么可以一次填满,

但如果c<q,不可能一次填满,此时可以分割成两个事件,mex(c,k)和mex(s,k),

其中对于mex(s,k),mex(s,s) 是先手必败,即P态,mex(s,k+1)...mex(s,s-1)都是先手必胜,即N态,

所有移动都导致N态局面的是P态,所以显然mex(s,k)是P态,那么mex(s,k)显然与mex(k,c)等价

 1 #include<stdio.h>
 2 #include<cmath>
 3 #include<cstring>
 4 using namespace std;
 5 const int MAXN = 1000010;
 6 int mex(int s, int c){
 7     if( c == 0 || s == c)
 8         return 0;
 9     int q = sqrt(s);
10     while( q+q*q >= s)
11         q--;//最大的不能一次填满的数
12     if(c > q) return s-c;
13     else return mex(q,c);
14 }
15 int main(){
16     int N;
17     int ans;
18     int s, c;
19     int T = 0;
20     while(~scanf("%d",&N)&&N){
21         ans  = 0;
22         for(int i = 0; i < N; ++i){
23             scanf("%d%d",&s,&c);
24             ans = ans^mex(s,c);
25         }
26         printf("Case %d:\n",++T);
27         if(ans)
28             puts("Yes");
29         else
30             puts("No");
31     }
32 }

 

hdoj 1729 Stone Games(SG函数)

标签:

原文地址:http://www.cnblogs.com/blueprintf/p/4722150.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!