传送门
题意:Alice先手,与Bob轮流进行拿石子操作,每次从一堆石子中拿出 k(k>0) 颗石子则从另外一堆拿出 k*s(s>=0) 颗石子。谁无法进行操作谁输掉比赛。
思路:说实话是不怎么知道这个博弈该怎么写的,听说赛中许多人都是打表过的这题(就很绝)。赛后看其他大佬题解才知道这个题其实是可以暴力卡过去的。
我们初始化标记 f[i][j] ==1 表示初始两堆石子为 i和j 时为必赢态,反之为必输态。然后我们枚举 i 和j,再分别枚举 k和s 处理 f[i+k][j+k*s] 和 f[i+k*s][j+k] (因为两堆初始石子互换状态是一致的)。
最后注意下输入输出卡时长即可。
代码实现:
#include<bits/stdc++.h>
using namespace std;
const int N = 5010;inline void read(int &x){char t=getchar();while(!isdigit(t)) t=getchar();for(x=t^48,t=getchar();isdigit(t);t=getchar()) x=x*10+(t^48);
}int T = 1, n, m;
bool f[N][N];int main()
{for(int i = 0; i <= 5000; i ++){for(int j = 0; j <= 5000; j ++){if(!f[i][j]){for(int k = 1; i+k <= 5000; k ++)for(int s = 0; j+k*s <= 5000; s ++)f[i+k][j+k*s] = 1;for(int k = 1; j+k <= 5000; k ++)for(int s = 0; i+k*s <= 5000; s ++)f[i+k*s][j+k] = 1;}}}read(T);while(T --){read(n); read(m);if(f[n][m]) puts("Alice");else puts("Bob");}return 0;
}