Alice and Bob
题意:
两人博弈,每次一个人从一堆中拿k个,同时从另一堆拿k * s(s>=0)个,问谁先不能拿
10000组数据,N<=5000
题解:
(x,y)表示第一堆石头数量为x,第二堆为y
如果(x,y)是必败状态,那么通过取走石头一次直接形成(x,y)的(x1,y1)必然不是必败状态
如果(x,y)不是必败状态,那(x1,y1)就不一定了
可以通过反证去理解
指向必败状态的是必胜状态,必胜状态可以指向必败,也可以指向必胜。必败状态无法到必败状态
综上:我们只需要关注一个点是否可以由必败点得到,如果可以,该点不是必败点,否则是必败点
此时复杂度为O(n4),但是要知道一个结论:对于一个的i只存在至多一种j后手能够获胜
证明如下:
若存在(i,q)(i,p)(p>q)满足后手胜,那么Alice只需将(i,p)->(i,q)即可获胜,不满足后手胜的条件。
这样复杂度就大约在O(n3)
代码:
#include<iostream>
#include<stdio.h>
using namespace std;
bool f[5001][5001];
int main()
{ for(int i=0;i<=5000;i++)//自小到大枚举i,jfor(int j=0;j<=5000;j++){if(f[i][j]==0)//对于每种必败态进行拓展{for(int k=1;k+i<=5000;k++)for(int s=0;s*k+j<=5000;s++)f[i+k][j+s*k]=1;for(int k=1;k+j<=5000;k++)for(int s=0;s*k+i<=5000;s++)f[i+s*k][j+k]=1;}}int t,n,m;cin>>t;while(t--){scanf("%d%d",&n,&m);if(f[n][m]==0){puts("Bob");}else puts("Alice");}return 0;
}