题解 加与乘
发现 A 先手时 A 必败的条件是
序列的两端存在 0 或 序列中存在 \(\geqslant 2\) 个连续 0 或 存在长度为偶数的全 1 序列
前两个条件是因为这两个性质 B 可以一直保持
最后一个是因为 A 将其消完后会出现两个连续 0
B 先手时 A 必败条件是 B 可以用恰好一次操作弄出 A 先手时 A 必败的序列
大力分类讨论即可
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 100010
#define ll long long
//#define int long long
char buf[1<<21], *p1=buf, *p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
inline int read() {
int ans=0, f=1; char c=getchar();
while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
return ans*f;
}
int n, m;
int a[N];
namespace force{
int f[25][1<<22];
int encode(int* a, int n) {
int ans=0;
for (int i=1; i<=n; ++i) ans|=a[i]<<i;
return ans;
}
void decode(int* a, int n, int code) {
for (int i=1; i<=n; ++i)
if (code&(1<<i)) a[i]=1;
else a[i]=0;
}
int dfs(int now, int n, int s) {
if (~f[n][s]) return f[n][s];
bool any_win=0, any_lose=0;
int *t=&f[n][s], sta[22], tem[22];
memset(sta, 0, sizeof(sta));
memset(tem, 0, sizeof(tem));
decode(sta, n, s);
if (n==1) {return *t=(sta[1]==0);}
for (int i=1; i<n; ++i) {
for (int j=1; j<i; ++j) tem[j]=sta[j];
for (int j=i+2; j<=n; ++j) tem[j-1]=sta[j];
tem[i]=sta[i]^sta[i+1];
if (dfs(now^1, n-1, encode(tem, n-1))) any_win=1;
else any_lose=1;
tem[i]=sta[i]&sta[i+1];
if (dfs(now^1, n-1, encode(tem, n-1))) any_win=1;
else any_lose=1;
}
if (!now) *t=any_win?1:0; // A first
else *t=any_lose?0:1;
// cout<<"dfs: "<<now<<' '<<n<<" ("; for (int i=1; i<n; ++i) cout<<sta[i]<<','; cout<<sta[n]<<") "<<*t<<endl;
return *t;
}
void init() {memset(f, -1, sizeof(f));}
void solve() {
for (int i=1; i<=n; ++i) a[i]&=1;
puts(dfs(m, n, encode(a, n))?"A":"B");
}
}
namespace task{
void solve() {
for (int i=1; i<=n; ++i) a[i]&=1;
if (!m) {
if (!(a[1]&a[n])) {puts("A"); return ;}
for (int i=2; i<=n; ++i) if (a[i-1]==0 && a[i]==0) {puts("A"); return ;}
int cnt=0; a[n+1]=0;
for (int i=1; i<=n+1; ++i) {
if (a[i]&1) ++cnt;
else {
if (!(cnt&1)) {puts("A"); return ;}
else cnt=0;
}
}
puts("B");
}
else {
if (!(a[1]|a[n])) {puts("A"); return ;}
bool once=0;
if (!(a[1]&a[n])) once=1;
for (int i=2; i<=n; ++i) if (a[i-1]==0 && a[i]==0) {
if (once) {puts("A"); return ;}
else once=1;
}
int cnt=0; a[n+1]=0;
for (int i=1; i<=n+1; ++i) {
if (a[i]&1) ++cnt;
else {
if (!(cnt&1)) {
if (once) {puts("A"); return ;}
else once=1;
}
else cnt=0;
}
}
puts(once?"B":"A");
}
}
}
signed main()
{
freopen("game.in", "r", stdin);
freopen("game.out", "w", stdout);
int T=read();
force::init();
while (T--) {
n=read(); m=read();
for (int i=1; i<=n; ++i) a[i]=read();
// if (n>30) puts("A");
// else force::solve();
if (n<=2) force::solve();
else task::solve();
}
return 0;
}