您的位置:首页 > 其它

威佐夫博弈(高精度)

2017-04-15 17:49 176 查看
威佐夫博弈详解

只要形成了奇异局势,那么下个人必须;

威佐夫博弈:

 有两堆各若干个物品,两个人轮流从某一堆或同时从两堆中取同样多的物品,规定每次至少取一个,多者不限,最后取完者得胜。这种情况下是颇为复杂的。

可以用两个数(a[k],b[k])(ps:(a[k]≤b[k])k为一个自然数)表示两堆物品的数量。如果该数量为奇异局势,那么先手输;

前几个奇异局势如下:(0,0,)、(1,2)、(3,5)、(4,7)、(6,10)······起始值a[0]=b[0]=0;k=0;

可以看出a[k]是在之前未出现过的最小自然数,而b[k] = a[k]+k,k代表出现的第几个奇异局势;

性质:

1.任何自然数都包含在一个且仅有一个的奇异局势中。

证明:若(a[k],b[k])为一个奇异局势,因为b[k]=a[k]+k,a[k]>a[k-1]  =》  b[k] >a[k-1]+k >a[k-1]+k-1 =》 b[k-1] > a[k-1].

2.任何操作都会将奇异局势变成非奇异局势

由性质1可知,即使是同时减少,两个数的差值不变,所以不可能成为其他奇异局势的差,因此也是非奇异局势;

3.可采用适当的方法将非奇异局势变为奇异局势,那么下一个必输;

 
结论:两个人如果都采用正确操作,那么面对非奇异局势,先拿者必胜;反之,则后拿者取胜。
那么任给一个局势(a,b),怎样判断它是不是奇异局势呢?
我们有如下公式:a表示第一堆的个数,b表示第二堆的个数,c表示二者之差,当然a必须小于b;
再找规律的话我们会发现,a= c* 1.618 

而1.618 = (sqrt(5)+ 1) /  2 。



将黄金分割率的24位小数分为三部分

按照多项式乘法可以得到下面的代码

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;

#define LL long long
#define MOD 1000000000
LL temp[3]={618033988,749894848,204586834};

int main()
{
LL n,m,T;
//freopen("in.txt","r",stdin);
scanf("%lld",&T);
while(T--)
{
scanf("%lld%lld",&n,&m);
if(n<m)
swap(n,m);
LL diff=n-m;

LL ta=diff/MOD,tb=diff%MOD;
LL ans=tb*temp[2];
ans=ans/MOD+ta*temp[2]+tb*temp[1];
ans=ans/MOD+ta*temp[1]+tb*temp[0];
ans=ans/MOD+ta*temp[0]+diff;
puts(ans==m?"B":"A");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: