因为以前写过类似的博弈,所以很快想出来了

因 为 从 点 i 出 发 , 假 设 可 以 去 点 x 1 , x 2 , x 3 . . . . . . . 因为从点i出发,假设可以去点x_1,x_2,x_3....... i,x1,x2,x3.......

在 能 去 的 这 些 路 径 下 , 只 要 有 一 条 是 必 胜 路 径 就 赢 了 在能去的这些路径下,只要有一条是必胜路径就赢了 ,

所 以 设 d p [ i ] 为 硬 币 在 i 位 置 先 手 是 否 必 胜 所以设dp[i]为硬币在i位置先手是否必胜 dp[i]i

所 以 对 于 每 个 位 置 s , 向 s + a [ s ] , s + 2 a [ s ] . . . 连 边 所以对于每个位置s,向s+a[s],s+2a[s]...连边 s,s+a[s],s+2a[s]...

当 然 也 要 对 s − a [ s ] , s − 2 a [ s ] 连 边 ( 在 满 足 移 动 条 件 的 情 况 下 ) 当然也要对s-a[s],s-2a[s]连边(在满足移动条件的情况下) sa[s],s2a[s]()

接下来就好办了,无脑dfs就行

也 许 你 听 的 不 是 很 明 白 , 没 关 系 , 代 码 很 好 理 解 , 简 短 也许你听的不是很明白,没关系,代码很好理解,简短 ,,,

#include <bits/stdc++.h>
using namespace std;
const int maxn=2e5+10;
int n,a[maxn],dp[maxn];//表示先手是否能赢 
vector<int>vec[maxn];
int dfs(int u)
{
	if(dp[u]!=-1)	return dp[u];
	int flag=0;	
	for(int i=0;i<vec[u].size();i++)
	{
		int v=vec[u][i];
		if( dfs(v) )	continue;//后手能赢,也就是先手输
		else	flag=1;//先手赢,标记 
	}
	if(flag)	return dp[u]=1;//只要有1种赢的可能,因为最优策略,所以必胜 
	else	return dp[u]=0;
}
int main()
{
	cin >> n ;
	for(int i=1;i<=n;i++)	cin >> a[i];
	for(int i=1;i<=n;i++)
	{
		for(int j=i+a[i];j<=n;j+=a[i])
			if(a[i]<a[j])	vec[i].push_back(j);//i能去j 
		for(int j=i-a[i];j>=1;j-=a[i])
			if(a[i]<a[j])	vec[i].push_back(j);//i能去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');
}