题目链接:hdu 5708
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65535/65536 K (Java/Others)
Problem Description
Alice and Bob are playing a stone game in a board of n×m cells.
In the begining, the stone is in the upperleft cell. And in each turn, they can move the stone one cell to the right or one cell down, or diagonally k cells down to the right, which means if you are at (x,y), then you could move into (x+1,y), (x,y+1) or (x+k,y+k) at the next step. The player who can not move loses. They play in turns and Alice moves first.
Now given n, m and k, could you tell me who is the winner?
Input
First line contains an integer T(1≤T≤10), denoting the number of test cases.
In each test case, the first line is two integers Q and k.
In the following Q lines, each line contains n and m.(1≤Q≤1000,1≤k,n,m≤109)
Output
For each test case, output Q lines.
If Alice is the winner, output “Alice”. Otherwise “Bob”.
Sample Input
2
2 1
4 5
3 4
2 3
4 5
5 6
Sample Output
Alice
Alice
Alice
Bob
翻以前的比赛翻到这道题,之前女生赛期间对这道题根本无从下手,现在一看觉得可以做,于是画起了表,不过果然光凭画表还是比较难找规律,最后还是代码打表才找出了规律。
PS:这题过的人不多,是不会的人不会做,会的都懒得做嘛Orz。
以防万一说一下:如果有人不知道sg函数是啥就过来看这篇博客的话,你肯定连打表代码都看不懂,快去搜下sg函数和尼姆博弈。不过搜完看完,这道题基本就会了=。=
WA了一下,发现k = 1的时候还要特判一下Orz。
打表码:
#include
#include
#include
#include
#include
#include
#include
#define M 21
#define mod 1000000007
#define INF -0x3f3f3f3f
using namespace std;
int g[M][M];
void sg(int k)
{
for(int i = 2; i <= M; i += 2)
{
g[i + 1][1] = g[1][i + 1] = 0;
g[i][1] = g[1][i] = 1;
}
for(int i = 2; i <= M; i++)
{
for(int j = 2; j <= M; j++)
{
if((!g[i - 1][j]) || (!g[i][j - 1]) || ((!g[i - k][j - k]) && (i - k > 0) && (j - k > 0)))
{
g[i][j] = 1;
continue;
}
else
{
g[i][j] = 0;
}
}
}
}
int main()
{
int T;
scanf("%d", &T);
while(T--)
{
int k;
scanf("%d", &k);
sg(k);
for(int j = 1; j <= M; j++)
{
for(int k = 1; k <= M; k++)
{
printf("%d ", g[j][k]);
}printf("\n");
}printf("\n\n\n\n");
return 0;
}
ac码:
#include
#include
#include
#include
#include
#include
#include
#define M 21
#define mod 1000000007
#define INF -0x3f3f3f3f
using namespace std;
int main()
{
int T;
scanf("%d", &T);
while(T--)
{
int q, k;
scanf("%d %d", &q, &k);
while(q--)
{
int n, m, t;
scanf("%d %d", &n, &m);
if(n < m)//由于表是关于主对角线对称的,为了判断方便让m保持是n和m中比较小的那个值。
{
t = n;
n = m;
m = t;
}
if(k == 1)
{
if(m % 2)
{
if((n - m) % 2)
printf("Alice\n");
else
printf("Bob\n");
}
else
{
printf("Alice\n");
}
}
else
{
t = 2 * (k + 1);//循环周期
if((m % t >= 1) && (m % t <= k))
{
if((n - m) % 2)
printf("Alice\n");
else
printf("Bob\n");
}
else if(!(m % (k + 1)))
printf("Alice\n");
else
{
if((n - m) % 2)
printf("Bob\n");
else
printf("Alice\n");
}
}
}
}
return 0;
}