题意:给你一个数字n,每次把数字n分割成k份,轮到谁不能分了谁就输了,小A先手,如果小A赢了输出1,否则输出0。
思路:用到了SG定理里的一个原理,如果你赢了,我肯定就输了,你输了我肯定就赢了,然后用DFS暴搜一下模拟分割,刚开始也不知道怎么写的。。乱七八糟,。。后来大佬帮忙改了一下代码,思路一下子就清晰起来。。
AC代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
typedef long long ll;
ll h[24];
ll n, m;
void init(){
h[0] = 1;
for(int i = 1; i <= 19; i++){
h[i] = h[i-1]*10;
}
}
int dfs(ll x1,ll x2, int k){ //x1:前面加起来的数 x2:现在的数。
if(k == 0){
if(dfs(0, x1+x2, m) == 1 //如果下次DFS答案为1,则说明这次拿的人输了
return 0;
return 1;
}
for(int i = 1; x2 >= h[i]; i++){ //从后往前分割
int ans = dfs(x1+x2%h[i], x2/h[i], k-1);
if(ans == 1)
return 1;
}
return 0;
}
int main(){
init();
while(scanf("%lld%lld",&n,&m)!=EOF){
m--; //分割成m份, 就等于分割m--次
int ans = dfs(0, n, m);
printf("%d\n",ans);
}
return 0;
}