题目大意:有n个位置,每个位置有一个值a[i]。两个人轮流玩游戏。移动小球,小球假如当前在i位置,规则:找到一个位置j满足a[j]>a[i]且abs(j-i)%a[i]=0,这样就可以把球从i位置放到j位置。是不能移动小球的为loser。求当球初始位置在1~n时的输赢结果。
由于
a. 对于必胜态,一定有一个后继状态是必败的。
b. 对于必败态,所有后继都是必胜的。
没有后继为必败态
如3后继是1和2。其中1是必败态,2是必胜态。因为存在一个后继是必败态所以3为必胜态。
本题确定每个点的状态
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
int a[maxn];
int num[maxn];
int f[maxn];
int q[maxn];
vector<int >vt[maxn];
int main()
{
int n;
while(~scanf("%d",&n))
{
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
for(int i=1;i<=n;i++)
{
for(int j=i+a[i];j<=n;j+=a[i])
{
if(a[j]>a[i])
{
vt[j].push_back(i);///到j的点
num[i]++;///i能到达的地方个数
}
}
}
for(int i=1;i<=n;i++)
{
for(int j=i-a[i];j>=1;j-=a[i])
{
if(a[j]>a[i])
{
vt[j].push_back(i);///到j的点
num[i]++;///i能到达的地方de个数
}
}
}
memset(f,-1,sizeof(f));
int r=1;int l=1;
for(int i=1;i<=n;i++)
{
if(!num[i])
{
f[i]=0;
q[r++]=i;
}
}
while(l<r)
{
int u=q[l++];
for(int i=0;i<vt[u].size();i++)
{
int v=vt[u][i];
if(f[v]==-1)///v点还没确定,根据后继u确定v的必态
{
if(f[u]==0) f[v]=1;
else f[v]=0;
}
else///v之前已经确定过状态,就是v后继出现必败态,v就是必胜态
{
if(f[u]==0) f[v]=1;
}
num[v]--;
if(!num[v]) q[r++]=v;
}
}
for(int i=1;i<=n;i++)
{
if(f[i]) printf("A");
else printf("B");
}
printf("\n");
}
}