本题是博弈之中偏简单的,因为他没有很多的技巧,只要你处理的好就没问题,但是AC的关键往往在于细节,细节性的东西处理不好想要AC除非数据超级水,不然只会WA。那么这个题的思路就是首先判断是不是奇 异局势,如果是的话,就是0不是的话,就需要分几种情况考虑。
(1),两个数字都减小,同时减小一个数字。
(2),小的数字减小,大的不变。
(3),大的数字变小,小的不变。
居于这三种情况,如何判断?我们需要根据所有的奇异局势来判断。
如果你想用所给的两个数字和所以的奇异局势判断那样的话,很可能会石沉大海。我们考虑的方向应该是两个数字的差。因为这是一个标准。我们观察可以发现任何一个自然数都是可以通过奇异局势的两个数字相减得到,所以我们很自然的想到用这个作为标准。那么后面的就是讨论了,按照道理来说很多的不会发生的事情你写上去了不会错,但是如果数据比较怪的话,或者时间卡的比较精准的话,就会照成超时,所以能够不要的就不要相乘类似搜索里面的剪枝一样的,这个习惯很重要。无论是不是在搜索中,这都是要想到的。
我们按照自己有的a,b两个数字可以确定k=b-a(这里的b>a,但是题目中的是不一定的所以需要处理一下。)那么就以m[k],n[k]为界限来分析,就是三种情况(1)如果a>m[k],b>n[k],自然的剩下的石子数量就是a[k],b[k];
(2)如果a<m[k](b<n[k]),然后你就需要在m[k]之前寻找是不是有m[i]或者b[i]和a相等,是不是有m[i]或者n[i]和b相等,当然了有的情况是不需要考虑的因为是不可能出现的。这里就留给大家判断。
(3),如果a=m[k],那么你就挂了。
注意:上面还有一点就是1.2中的如果m,n相等的话,就会照成数据的重复输出,这里稍微注意一下就好了。
下面一个AC的代码:
#include<iostream> using namespace std; #include<cstdlib> #include<cmath> const int Max=1000005; int a[Max]; int b[Max]; int main() { int m,n; double p=5.0; int i,j,k; a[0]=0; b[0]=0; a[1]=1; b[1]=2; for(i=2;i<1000000;i++) { a[i]=i*(sqrt(p)+1.0)/2; b[i]=a[i]+i; } while(cin>>m>>n,m||n) { if(m>n) { i=m; m=n; n=i; } k=n-m; if(a[k]==m) { cout<<"0"<<endl; continue; } cout<<"1"<<endl; if(m<a[k]) { for(i=1;i<m;i++) { if(m==a[i]) if(b[i]<n) cout<<a[i]<<" "<<b[i]<<endl; if(m==b[i]) cout<<a[i]<<" "<<b[i]<<endl; if(n==b[i]) if(m>a[i]) { if(m!=n) cout<<a[i]<<" "<<b[i]<<endl; } } } else { cout<<a[k]<<" "<<b[k]<<endl; for(i=1;i<m;i++) if(m==b[i]) cout<<a[i]<<" "<<b[i]<<endl; for(i=1;i<m;i++) if(b[i]==n) { if(n!=m) cout<<a[i]<<" "<<b[i]<<endl; } } } return 0; }