威佐夫游戏:有两堆各若干个物品,两个人轮流从任意一堆中取出至少一个或者同时从两堆中取出同样多的物品,规定每次至少取一个,至多不限,最后取光者胜利。
经典博弈,推导过程可以去别处看,结论就是,
a = (int) ((b - a)*1.618),先手胜利
1.618 = (sqrt(5.0) + 1) / 2
代码:
#include <cstdio>
#include <cstring>
#include <stack>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <cmath>
#include <algorithm>
#include<bits/stdc++.h>
using namespace std;
const double N = 1e6+10;
const double pi = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int MOD = 1000000007;
#define ll long long
#define CL(a,b) memset(a,b,sizeof(a))
#define maxn 1000010
unsigned long long int n , m , x , y , t , k;
double a , b;
int main()
{
cin >> t;
while(t--)
{
cin >> x >> y;
n = min(x,y);
m = max(x,y);
a = double(m-n);
b = (sqrt(5.0) + 1) / 2;
k = (int)a*b;
if(k==n)
{
cout << "B" << endl;
}
else
{
cout << "A" << endl;
}
}
return 0;
}
如果范围太大的话,会存在精度问题。如果是(1 <= N <= 10^18)的话,需要模拟乘法。
#include <cstdio>
#include <cstring>
#include <stack>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <cmath>
#include <algorithm>
#include<bits/stdc++.h>
using namespace std;
const double N = 1e6+10;
const double pi = acos(-1.0);
const int INF = 0x3f3f3f3f;
#define ll long long
#define CL(a,b) memset(a,b,sizeof(a))
#define maxn 1000010
long long s[3]={618033988,749894848,204586834};
long long mod=1e9;
int main()
{
int t;
cin>>t;
long long a,b,k;
while(t--)
{
cin>>a>>b;
if(a>b)
swap(a,b);
k=b-a;
long long sum=0;
long long l=k/mod; //k的高九位
long long r=k%mod; //k的低九位
sum=r*s[2]; //最低位
sum=r*s[1]+l*s[2]+sum/mod; //倒二位.倒一位(如果没进位只剩倒二,否则+进位)
sum=r*s[0]+l*s[1]+sum/mod; //倒三位.倒二位倒一位
sum=k+l*s[0]+sum/mod; //0.618...(共27位),所以乘积除以三个1e9 最后加上1*k
if(a==sum)
cout<<"B"<<endl;
else
cout<<"A"<<endl;
}
return 0;
}