bzoj 3298: [USACO 2011Open]cow checkers -- 数学
3298: [USACO 2011Open]cow checkers
Time Limit: 10 Sec Memory Limit: 128 MBDescription
一天,Besssie准备和FJ挑战奶牛跳棋游戏。这个游戏上在一个M*N(1<=M<=1,000,000;1<=N<=1,000,000)的棋盘上,
这个棋盘上在(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),确定是谁赢。
Input
第1行:两个用空格隔开的整数M和N;
第2行:一个整数T;
第3到第T+2行:两个用空格隔开的整数x和y.
Output
第1到T行:包含“Farmer John”或者是“Bessie”,表示谁赢了这轮游戏。
Sample Input
3 3
1
1 1
1
1 1
Sample Output
Bessie
HINT
分析必败点,可以发现,必败点的同一行,同一列,同一对角线上的点都是必胜点
所以可知,每一列都只有一个点,并且这些点沿对角线对称
然后就可以O(n) 递推求出每一列的必败点,然后直接回答即可
#include<map> #include<cmath> #include<queue> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #define inf 1000000007 #define ll long long #define N 1000000 inline int rd() { int 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; } int a[N+10],n,m,T; int main() { a[1]=1;int tp=1; for(int i=1;i<=N;i++) { if(a[i]) continue; a[i]=a[tp]+i-tp+1;tp=i; if(a[i]<=N) a[a[i]]=i; } n=rd();m=rd();T=rd(); int x,y; while(T--) { x=rd()+1;y=rd()+1; if(a[x]==y||a[y]==x) puts("Farmer John"); else puts("Bessie"); } return 0; }
版权声明:本文为博主原创文章,未经博主允许不得转载。