POJ 1067 取石子游戏(威佐夫博弈)

题目链接:?id=1067

题面:

取石子游戏

Time Limit: 1000MSMemory Limit: 10000K

Total Submissions: 36951Accepted: 12512

Description

有两堆石子,数量任意,可以不同。游戏开始由两个人轮流取石子。游戏规定,每次有两种不同的取法,一是可以在任意的一堆中取走任意多的石子;二是可以在两堆中同时取走相同数量的石子。最后把石子全部取完者为胜者。现在给出初始的两堆石子的数目,如果轮到你先取,假设双方都采取最好的策略,问最后你是胜者还是败者。

Input

输入包含若干行,表示若干种石子的初始情况,其中每一行包含两个非负整数a和b,表示两堆石子的数目,a和b都不大于1,000,000,000。

Output

输出对应也有若干行,每行包含一个数字1或0,如果最后你是胜者,则为1,反之,则为0。

Sample Input

2 18 44 7

Sample Output

010

Source

NOI

解题:

慢慢推了几组之后,就会发现(1,2),(3,5),(4,7)……这些数对是必败态。推到这里想必大家都知道如何往下推了,(ai,bi),ai是之前没有出现过的最小自然数,而ci是之前没有出现过的最小自然数间隔,bi=ai+ci。为什么呢?因为(ai,bi-x),(bi>x>0)这些间隔在之前都已经出现过,只需要将两数共同减去相同一个数,便可到达必败态,故为必胜态。而(ai-x,bi),因为ai-x在前面都已经出现过,只需要将bi调整到前面(ai-x,bi-y)对应的必败态即可,故也为必胜态。只有(ai,bi),无法退回到之前的任一必败态,故为必败态。

序列为(1,2),(3,5),(4,7),(6,10),(8,13),(9,15),(11,18),(12,20),(14,23)……

推了这么多,,然而并无卵用。

因为这是普通人都不可能一眼发现的。

这是威佐夫的毕生研究,结论如下:

ai为[p*i],bi为[(p+1)*i],其中p为((sqrt(5.0)+1)/2)。[]为向下取整。

有了以上结论,那么此题就可以解了。(d=bi-ai),用此时的d带入ai的计算公式,算出ai’,看ai’是否等于给出的ai,是则说明为必败态,不是则说明不是必败态。

详细证明:

代码:

#include <iostream>#include <cstdio>#include <cmath>#include <cstring>#include <string>#include <set>using namespace std;int main(){int a,b,dif,tmp;while(cin>>a>>b){if(a>b)swap(a,b);dif=b-a;tmp=dif*(1.0+sqrt(5.0))/2;if(a==tmp)cout<<"0\n";else cout<<"1\n";}return 0;}

版权声明:本文为博主原创文章,未经博主允许不得转载。

无论如何,没有人有办法把自己抑或他人的刺拔掉。那是一碰便痛的软肋,

POJ 1067 取石子游戏(威佐夫博弈)

相关文章:

你感兴趣的文章:

标签云: