POJ 1067 取石子游戏 (威佐夫博奕,公式)
题意:
有两堆石子,两个人轮流取石子。规定每次有两种取法,一是可以在任意的一堆中取走任意多的石子;二是可以在两堆中同时取走相同数量的石子。最后把石子全部取完者为胜者。给定两堆石子数量,问先手的输赢?
思路:
设 a<b
k=a-b
x=(1 + sqrt(5)) / 2
若 a==k*x 则必输!否则,必胜。
简单来讲,判断先手输赢靠的就是两堆石子数量的差的大小,如果两堆之差乘以一个特定的数字,刚好就是小堆的数目,那么必输。
这个特定的数字的神奇之处在哪?
根号5即 sqrt(5) = 2.2360679774998
x=(2.236+1)/2=1.618左右
1 #include <iostream> 2 #include <cmath> 3 #include <cstdio> 4 using namespace std; 5 int main() 6 { 7 //freopen("input.txt", "r", stdin); 8 int a, b; 9 double x=(1+sqrt(5.0))/2; 10 while(cin>>a>>b) 11 { 12 if(a>b) 13 { 14 int tmp=b; 15 b=a; 16 a=tmp; 17 } 18 int k=b-a; 19 if(a==(int)(k*x+0.5)) //必输 20 cout<<"0"<<endl; 21 else 22 cout<<"1"<<endl; 23 } 24 return 0; 25 }