威佐夫博弈(Wythoff's game):有两堆各若干个物品,两个人轮流从任意一堆中取出至少一个或者同时从两堆中取出同样多的物品,规定每次至少取一个,至多不限,最后取光者胜利。
先找出必败态 (0 0) (1 2) (3 5) (4 7) (6 10) (8 13) (a b)
结论 a=(b-a)*((sqrt(5.0) + 1) / 2) (sqrt(5.0) + 1) / 2==1.618
威佐夫博弈变形:有两堆各若干个物品,两个人轮流从任意一堆中取出至少一个或者同时从两堆中取出分别取出(x,y)的物品|x-y|<=k,规定每次至少取一个,至多不限,最后取光者胜利。
公式:所有的必败态为( floor((1.0-k+sqrt(k*k+2*k+5.0))*n/2.0) , floor((3.0+k+sqrt(k*k+2*k+5.0))*n/2.0) );
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn=2005; double k; ll f(ll n){ return floor((1.0-k+sqrt(k*k+2*k+5.0))*n/2.0); } ll ff(ll n){ return floor((3.0+k+sqrt(k*k+2*k+5.0))*n/2.0); } int main(){ int T; scanf("%d",&T); while(T--){ ll a,b; scanf("%lld%lld%lf",&a,&b,&k); if(a>b) swap(a,b); ll l=1,r=100000000,mid; while(l<=r){ mid=(l+r)/2; if(f(mid)>=a) r=mid-1; else l=mid+1; } r++; ll l1=1,rr=100000000,mmid; while(l1<=rr){ mmid=(l1+rr)/2; if(ff(mmid)>=b) rr=mmid-1; else l1=mmid+1; } rr++; if(r==rr&&f(r)==a&&ff(rr)==b) printf("0\n"); else printf("1\n"); } }