威佐夫游戏

1072 威佐夫游戏 
基准时间限制:1 秒 空间限制:131072 KB 分值: 0  难度:基础题
 收藏
 关注
有2堆石子。A B两个人轮流拿,A先拿。每次可以从一堆中取任意个或从2堆中取相同数量的石子,但不可不取。拿到最后1颗石子的人获胜。假设A B都非常聪明,拿石子的过程中不会出现失误。给出2堆石子的数量,问最后谁能赢得比赛。
例如:2堆石子分别为3颗和5颗。那么不论A怎样拿,B都有对应的方法拿到最后1颗。
Input
第1行:一个数T,表示后面用作输入测试的数的数量。(1 <= T <= 10000)
第2 - T + 1行:每行2个数分别是2堆石子的数量,中间用空格分隔。(1 <= N <= 2000000)
Output
共T行,如果A获胜输出A,如果B获胜输出B。
Input示例
3
3 5
3 4
1 9
Output示例
B
A
A

威佐夫博弈:(来自百度百科)威佐夫博弈(Wythoff's game):有两堆各若干个物品,两个人轮流从任一堆取至少一个或同时从两堆中取同样多的物品,规定每次至少取一个,多者不限,最后取光者得胜。

这种情况下是颇为复杂的。我们用(a[k],b[k])(a[k] ≤ b[k] ,k=0,1,2,...,n)(表示两堆物品的数量并称其为局势,如果甲面对(0,0),那么甲已经输了,这种局势我们称为奇异局势。前几个奇异局势是:(0,0)、(1,2)、(3,5)、(4,7)、(6,10)、(8,13)、(9,15)、(11,18)、(12,20)。注:k表示奇异局势的序号, 第一个奇异局势k=0。

可以看出,a[0]=b[0]=0,a[k]是未在前面出现过的最小自然数,而 b[k]= a[k] + k。

可根据规律求出奇异局势

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define maxn 2000005
#define inf 0x3f3f3f
#define ll long long
#define mod 1000000007
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
int a[maxn];bool vis[2*maxn];
void init(){
    a[1]=2;vis[1]=vis[2]=true;
    int x=2,y=2;
    while(x<2000001){
        while(vis[x]==true)x++;
        vis[x]=true;
        a[x]=x+y;vis[x+y]=true;
        y++;
    }
}
int main(){
    mem(a,0);mem(vis,false);
    init();
    int t;cin>>t;
    while(t--){
        int m,n;cin>>m>>n;
        if((m==0&&n==0)||a[m]==n||a[n]==m)cout<<"B"<

1185 威佐夫游戏 V2 
基准时间限制:1 秒 空间限制:131072 KB 分值: 0  难度:基础题
 收藏
 关注
有2堆石子。A B两个人轮流拿,A先拿。每次可以从一堆中取任意个或从2堆中取相同数量的石子,但不可不取。拿到最后1颗石子的人获胜。假设A B都非常聪明,拿石子的过程中不会出现失误。给出2堆石子的数量,问最后谁能赢得比赛。
例如:2堆石子分别为3颗和5颗。那么不论A怎样拿,B都有对应的方法拿到最后1颗。
Input
第1行:一个数T,表示后面用作输入测试的数的数量。(1 <= T <= 10000)
第2 - T + 1行:每行2个数分别是2堆石子的数量,中间用空格分隔。(1 <= N <= 10^18)
Output
共T行,如果A获胜输出A,如果B获胜输出B。
Input示例
3
3 5
3 4
1 9
Output示例
B
A
A


威佐夫游戏其中一个特点是奇异局势的每一个较小值乘以1+黄金分割值(0.618.....),即(1+sqrt(5))/2;

但是这个题目里有精度要求,所以按照乘法的原则,把这个数的精度减小。

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define maxn 2000005
#define inf 0x3f3f3f
#define ll unsigned long long
#define mod 1000000000
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
ll tmp[3] = {618033988,749894848,204586834};
int main(){
    int n;ll a,b;
    cin>>n;
    while(n--){
        cin>>a>>b;
        if(a>b)swap(a,b);
        ll c=b-a;
        ll x=c/mod,y=c%mod;
        ll t=y*tmp[2];
        t=x*tmp[2]+y*tmp[1]+t/mod;
        t=x*tmp[1]+y*tmp[0]+t/mod;
        t=c+x*tmp[0]+t/mod;
        if(t==a)cout<<"B"<

你可能感兴趣的:(博弈论)