2021暑期牛客多校1-A
A
最重要的结论,任意两个先手必败态不会有重复的数字(不考虑两个位置交换)。
于此,可以得到先手必败的个数的上限和 \(n\) 是同阶的。
考虑将所有先手必败的情况找出来然后打表。
从小到大枚举石子个数 \(i, j\ (i<j)\) ,考虑 \((i,j)\) 是否为先手必败。
发现如果其能一步走到之前某一个先手必败,那么必是先手必胜,否则就是先手必败。
因为只能从更大的必败走向更小的必败,又是从小到大枚举,所以一步走到的先手必败态一定是已经发现的。
复杂度 \(\Theta(N^2*sum\_failed)\) ,可以在本机30s左右跑完
// 打表
#include <map>
#include <set>
#include <cmath>
#include <queue>
#include <cstdio>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define ll long long
#define LL long long
#define ull unsigned long long
#define cint const int&
#define Pi acos(-1)
const int mod = 1e9+7;
const int inf_int = 0x7fffffff;
const ll inf_ll = 0x7fffffffffffffff;
const double ept = 1e-9;
int pre[5050][2], cnt;
int al[2000], be[2000];
int main() {
freopen("1.out", "w", stdout);
const int n = 5000;
pre[++cnt][0] = 0;
pre[cnt][1] = 0;
for(int i=2; i<=n; i++) {
for(int j=i+1; j<=n; j++) {
bool flag = 1;
for(int k=1; k<=cnt && flag; k++) {
int r1 = i-pre[k][0];
int r2 = j-pre[k][1];
if(!(r1*r2)) {
flag = 0;
break;
}
if(r1 > 0 && r2 > 0) {
if(!(r1%r2) || !(r2%r1)) {
flag = 0;
break;
}
}
r1 = i-pre[k][1];
r2 = j-pre[k][0];
if(!(r1*r2)) {
flag = 0;
break;
}
if(r1 > 0 && r2 > 0) {
if(!(r1%r2) || !(r2%r1)) {flag = 0; break;}
}
}
if(flag) {
pre[++cnt][0] = i;
pre[cnt][1] = j;
al[cnt] = i;
be[cnt] = j;
}
}
}
for (LL i = 1;i <= cnt; ++ i){
printf("%d,", al[i]);
}
cout << endl;
for (LL i = 1;i <= cnt; ++ i){
printf("%d,", be[i]);
}
cout << endl;
cout << cnt;
return 0;
}