威佐夫博弈(高精度)

来源:互联网 发布:阿里云备案承诺书demo 编辑:程序博客网 时间:2024/06/05 07:02

威佐夫博弈详解

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

威佐夫博弈:

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

可以用两个数(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 1000000000LL 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;}


0 0
原创粉丝点击