参考博客:https://www.cnblogs.com/csushl/p/9943000.html

威佐夫博弈

题目链接:http://poj.org/problem?id=1067

两堆石子,每次可以取一堆或两堆,从两堆中取得时候个数必须相同,先取完的获胜。

那么任给一个局势(a,b),怎样判断它是不是奇异局势呢?我们有如下公式:

ak =[k(1+√5)/2],bk= ak + k  (k=0,1,2,…,n 方括号表示取整函数)

图片说明
图片说明

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>

using namespace std;

int n,m;

int main()
{
    double k=(1+sqrt(5.0))/2;
    while( cin>>n>>m )
    {
        if( n>m ) swap(n,m);
        int t=m-n;
        if( n==(int) ( (double)t*k ) ) puts("0");
        else printf("1\n");
    } 
} 

威佐夫博弈II

2020HDU暑假多校赛第九场 http://acm.hdu.edu.cn/showproblem.php?pid=6869

两堆石子,每次可以取一堆或两堆,从两堆中取得时候个数的差值小于等于k,先取完的获胜。
那么任给一个局势(a,b),怎样判断它是不是奇异局势呢?我们有如下公式:
图片说明
图片说明
图片说明

#include<bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;

ll readint(){
    ll x=0,f=1; char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}

ll a,b,k;

int main(){
    int T=readint();
    while( T-- )
    {
        a=readint(); b=readint(); k=readint();
        if(a>b) swap(a,b);
        ll n=b-a;
        n/=(k+1);
        ld tmp=sqrt(k*k+2*k+5);
        ld x=(1-k+tmp)/2.0,y=(3+k+tmp)/2.0;
        if( (ll)(x*n)!=a || (ll)(y*n)!=b ) puts("1");
        else puts("0");
    }
    return 0;
}