做hdu2176的時候就準備做這題,發現不會。今天看着解題報告,做的。囧。記憶力實在是差。看來還是得遵守記憶曲線。溫故而知新。
理論:(來自:http://www.wutianqi.com/?p=1081)
下面解題報告來自:http://blog.csdn.net/liwen_7/article/details/7937113
那麼任給一個局勢(a,b),怎樣判斷它是不是奇異局勢呢?我們有如下公式:
對於某個局勢(a,b) ,b>=a
差值k=b-a
對於某個確定的k
有唯一的奇異局勢(必敗點) (a_k,b_k) 其中a_k=k*(1+sqrt(5))/2 b_k=a_k+k
如果a,b是奇異局勢 則輸出0
不是的話輸出1(通過某種操作可以獲勝)
已知a,b
操作分5種
1.a==b
同時減去a 得到0,0
2.a==a_k b>b_k
b -(b-b_k)
3.a==a_k b<b_k
同時拿走a_k-a_(b-a_k)
得到 a_(b-a_k) a_(b-a_k) + b-a_k
4.a>a_k b==b_k
從a中拿走 a-a_k
5.a<a_k b==b_k
5.1 a==a_ j (j<k)
b-(b-b_ j)
得到 a_ j b_ j
5.2 a==b_ j (j<k)
b-(b-a_ j)
得到 b_ j a_ j
#include<iostream> #include<string.h> #include<math.h> using namespace std; int main() { int n, m; int k; double x=(1+sqrt(5.0))/2; while(scanf("%d%d",&n,&m)!=EOF && n+m) { if(n>m) //如果 n > m,根據奇異局勢應該要a<b { n^=m; //通過三個異或 交換n、m m^=n; n^=m; } k=m-n; //顯然,遇到奇異局勢的人一定會輸。 if((int)(k*x)==n) printf("0\n"); //因爲奇異局勢變成非奇異局勢後,下一個人一定可以將局勢 //再次變成奇異局勢,所以一定還是第一次遇到奇異局勢的人遇到奇異局勢,則他定輸 else { printf("1\n");//碰到非奇異局勢,將其變成奇異局勢,可能有兩種變法。 for(int i=1;i<=n;i++)//①:同時從兩堆中拿相同數目的石子。 { int a=n-i , b=m-i; k=b-a; //cout<<"a= "<<a<<" b= "<<b<<" "<<x<<endl; if((int)(k*x)==a) printf("%d %d\n",a, b); }//cout<<"111111111111"<<endl; for(int i=m-1;i>=0;i--)//②:從一堆中取。 { int a=n , b=i; if(a > b) //同理,保持奇異局勢中 a < b { a^=b; b^=a; a^=b; } k=b-a; if((int)(k*x)==a) printf("%d %d\n",a , b); }//cout<<"22222222222222"<<endl; } } return 0; }