题意:有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