因为以前写过类似的博弈,所以很快想出来了
因 为 从 点 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]连边(在满足移动条件的情况下) 当然也要对s−a[s],s−2a[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');
}