C. Permutation Game
铺垫
必胜态
当前玩家具有掌握胜局的状态
必败态
当前玩家无法摆脱输局的必然状态
在两个人的博弈中,一个人的胜利是建立在另一个人的失败的事实上,因而一个人若处于必胜态,那么另一个必然处于必败态。
题意
若一个\(a_j>a_i\),且\(|j-i|mod\space a_i==0\),当前玩家可以从i向j转移,从而将问题丢给下一个玩家。重复操作,直到一个玩家无法再继续转移下去。
在这题中必败态是必然存在的,因为最大值是无法再向其他位置转移的,即便是没有任何位置向最大值转移,第二大值也是必败态。同时任何能够向必败态转移的状态都是必胜态。
因而,我们可以在实际的处理的过程默认当前位置是必败态,如果能转到一个确切的必败态,再把当前位置的状态重新修改为必胜态。
同时用记忆化搜索来减少不必要的搜索量。
此外,作为博弈,每一个人都希望能够转移到一个对方为必败态的情况,这样自己就胜利了。
#include <bits/stdc++.h>
#define MEM(a,x) memset(a,x,sizeof(a))
#define W(a) while(a)
#define gcd(a,b) __gcd(a,b)
#define pi acos(-1.0)
#define PII pair<int,int>
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define ll long long
#define ull unsigned long long
#define rep(i,x,n) for(int i=x;i<n;i++)
#define repd(i,x,n) for(int i=x;i<=n;i++)
#define MAX 1000005
#define MOD 1000000007
#define INF 0x3f3f3f3f
#define lowbit(x) (x&-x)
using namespace std;
const int N = 1E5+20;
int n,dp[N],A[N];
vector<int > vec[N];
int dfs(int x)
{
if(dp[x]!=-1) return dp[x];
int defa=0;
for(int i=0;i<vec[x].size();i++)
{
if(!dfs(vec[x][i]))
{
defa=1;
break;
}
}
return dp[x]=defa;
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
cin>>A[i];
char c[N];
for(int i=1;i<=n;i++)
{
for(int j=i+A[i];j<=n;j=j+A[i])
if(A[j]>A[i])
vec[i].push_back(j);
for(int j=i-A[i];j>=1;j=j-A[i])
if(A[j]>A[i])
vec[i].push_back(j);
}
memset(dp,-1,sizeof(dp));
for(int i=1;i<=n;i++)
if(dp[i]==-1) dfs(i);
for(int i=1;i<=n;i++)
cout<<(dp[i]==1?'A':'B');//dp[i]=1代表必胜态 ,dp[i]代表必败态
return 0;
}