题目描述
有三堆石子,它们的石子个数分别为 x,y,z。
A 和 B 正在博弈,由 A 先手,双方轮流操作。
每次操作是指,选择若干堆(1~3 堆)石子,从中各取出相同数量的石子(不能 1 个都不取)。不能操作的人失
败。
请判定是否先手必胜。
先考虑两堆,先手必败的情况
(1,2),(3,5),(4,7),(6,10),(8,13);
每对两堆石子的差不相同,且每个数只出现了一次。
对于每个x,有唯一个y和它对应,出现先手必败的情况
考虑三堆 (a,b,c)
我们可以类比出每对a,b对应这有且只有一个c和它组成先手必败的情况。
对于(a,b,k)是先手必败的情况,c 为大于k的某一个数。
那么(a+c-k,b+c-k)组成先手必败的情况的第三堆的石子数不可能为c.
因为如果(a+c-k,b+c-k,c)为成先手必败的情况,那么先手同时在第1堆和第二堆取走c-k时(a,b,c)则为先手必败的情况,那么(a,b,k)则不可能为先手必败的情况,矛盾了所以(a+c-k,b+c-k)组成先手必败的情况的第三堆的石子数不可能为c.
同理(a+c-k,b),(a,b+c-k)为成先手必败的情况的第三堆的石子数也不可能为c。
那么c与(a,b)构成先手必败的情况的条件是,a和b没有在第三堆为c时出现过,a-b没有在第三堆为c时出现过。
#include<bits/stdc++.h>
using namespace std;
const int ha = 301;
int f[ha+5][ha+5], bu[ha+5][ha+5],vis[1000],cha[1000];
void yuchuli()
{
for(int i = 0; i <= ha; i++)
for(int j = 0; j <= ha; j++)
f[i][j] = 1e9;
memset(bu,0,sizeof(bu));
for(int cc = 0; cc <= ha; cc++)
{
int c = cc + 1;
for(int a = 0; a <= ha; a++)
for(int b = 0; b <= a; b++)
{
if(f[a][b] < cc)
{
int k = f[a][b];
int v = cc - k;
if((a + v) <= ha) bu[a + v][b] = c;
if((b + v) <= ha) bu[a][b+ v] = c;
if(max(b+ v,a+ v) <= ha)bu[a+ v][b+v] = c;
}
else if(max(bu[a][b],bu[b][a]) < c && (vis[a] < c) && (vis[b] < c) && (cha[abs(a - b)] < c))
{
if(cc == 301)
int haha = 1;
f[a][b] = f[b][a] = cc;
vis[a] = c;
vis[b] = c;
cha[abs(a - b)] = c;
}
}
}
}
int main()
{
yuchuli();
int t;
cin >> t;
for(int i = 1; i <= t; i++)
{
int x,y,c;
scanf("%d%d%d",&x,&y,&c);
if(f[x][y] == c) cout << "No" << endl;
else cout << "Yes" << endl;
}
return 0;
}
.