bzoj3298 [USACO 2011Open]cow checkers 威佐夫博弈

版权声明:虽然是个蒟蒻但是转载还是要说一声的哟 https://blog.csdn.net/jpwang8/article/details/82595682

Description


一天,Besssie准备和FJ挑战奶牛跳棋游戏。这个游戏上在一个M*N的棋盘上,
这个棋盘上在(x,y)(0<=x棋盘的左下角是(0,0)坐标,棋盘的右上角是坐标(M-1,N-1)。
Bessie每次都是第一个移动棋子,然后Bessie与Fj轮流移动。每一轮可以做以下三种中的一种操作:
1)在同一行,将棋子从当前位置向左移动任意格;
2)在同一列,将棋子从当前位置向下移动任意格;
3)将棋子从当前位置向下移动k格再向左移动k格(k为正整数,且要满足移动后的棋子仍然在棋盘上)
第一个不能在棋盘上移动的人比赛算输(因为棋子处在(0,0)点)。
共有T个回合(1<=T<=1,000),每次给出一个新起始点的坐标(x,y),确定是谁赢。
1<=M<=1,000,000;1<=N<=1,000,000

Solution


威佐夫博弈裸题

有两堆物品记为(a,b),两个人轮流操作,每次操作后可以变成(a-n,b)、(a,b-n)、(a-n,b-n),其中n为不超过a、b的正整数
一个结论就是,当 ( b a ) 5 + 1 2 = a 时此局面为先手必败局面,然后这题就可以做了
我们把先手必败的局面按照a升序排序,可以发现每一个a都是前面没出现过的最小正整数,这是一个没什么用的性质

Code


#include <stdio.h>
#include <algorithm>
#include <math.h>

const double eps=0.00001;

int read() {
    int x=0,v=1; char ch=getchar();
    for (;ch<'0'||ch>'9';v=(ch=='-')?(-1):(v),ch=getchar());
    for (;ch<='9'&&ch>='0';x=x*10+ch-'0',ch=getchar());
    return x*v;
}

int main(void) {
    read(),read();
    for (int T=read();T--;) {
        int n=read(),m=read();
        if (n>m) std:: swap(n,m);
        double r=(sqrt(5.0)+1)*0.5*(m-n);
        if (n==(int)r) puts("Farmer John");
        else puts("Bessie");
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/jpwang8/article/details/82595682
今日推荐