题意:有n堆,2个人,每次可以从某1堆中取出任意个(至少1个),或者把一堆分成2个小堆。
题目分析:
一开始看到把1堆分成很多堆,我还有点小激动啊!可是刚准备写就发现,每一堆的可能石子数居然那么大(2^31-1)!坑爹啊!记忆化搜索肯定不行,数组都开不下。
……然后悲催的我,在昨天的停电+证明的摧残下又继续想了想。
(╯°Д°)╯( ┻━┻) !想不出来怎么换一种算法了! 然后我又去看解题报告了!!! T T……
最后居然是打表啊!打表啊!(╯°Д°)╯( ┻━┻(又是打表!还让不让人活了!))!
然后我苦逼地打了一张表……
贴出打的表吧……
1 #include<cstdio>
2 #include<algorithm>
3 #include<cstring>
4 #include<iostream>
5 using namespace std;
6 const int N = 999;
7 int sg[1001];
8 int dfs(int x){
9 if(sg[x] != -1)return sg[x];
10 bool g[1001] = {0};
11 int tp = dfs(x-1);
12 for(int i=1;i<=x;i++){
13 dfs(x-i);
14 g[sg[x-i]]=1;
15 }
16
17 for(int i = 1;i<(x)/2+1;i++){
18 int t = dfs(i)^dfs(x-i);
19 g[t] = 1;
20 }
21 for(int i = 0;;i++){
22 if(!g[i])return sg[x] = i;
23 }
24 }
25 int main()
26 {
27 #ifdef LOCALL
28 //freopen("in2.txt","r",stdin);
29 freopen("out.txt","w",stdout);
30 #endif
31 memset(sg,-1,sizeof sg);
32 dfs(N);
33 for(int i = 0;i<N;i++){
34 cout<<sg[i]<<endl;
35 }
36
37 return 0;
38 }
然后打出表如下:只列了20组——规律还是很明显的……从1开始,4个为一个循环节,第三个和第四个对调一下……
sg[0]:0
sg[1]:1
sg[2]:2
sg[3]:4
sg[4]:3
sg[5]:5
sg[6]:6
sg[7]:8
sg[8]:7
sg[9]:9
sg[10]:10
sg[11]:12
sg[12]:11
sg[13]:13
sg[14]:14
sg[15]:16
sg[16]:15
sg[17]:17
sg[18]:18
sg[19]:20
sg[20]:19
……
总之,以后如果数据太大,可以尝试打表(嘛……反正也暂时想不到其他方法)看有没有规律……
不过最后要说cxlove下面的评论简直让我有点欣慰……想不到啊想不到!如果不打表死也做不出来啊!谁知道要打表啊!丧心病狂!
番外:
窝:唉……还是意识不够……
Big窝:(╯°Д°)╯( ┻━┻(你以为LOL呢!还意识!))
窝:……T T