C. Permutation Game
題意:
兩人輪流移動鋼珠,誰最先不能移動就爲敗,移動規則: 且
題解:
若當前點的後繼點都爲必勝點,那此點爲必敗點,反之爲必勝點 — 博弈論
觀察當前點能到達的點的狀態就能判斷當前點的狀態,因爲一個點的後繼點必須滿足 ,所以要先從權值大的點開始標記狀態
代碼:
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
const int MAXN = 2e5+55;
int arr[MAXN]; // 記錄每個位置的權值
int pos[MAXN]; // 標記權值的位置
int dp[MAXN]; // 標記每個位置的狀態
int main()
{
int n,val;
cin>>n;
for(int i=1;i<=n;++i)
{
cin>>arr[i];
pos[arr[i]] = i;
}
for(int i = n;i>=1;--i) //權值從大到小
{
for(int j=pos[i]+ i;j<=n;j += i) //位置向後移動權值的整數倍
{
if(arr[j]>i && dp[j]==2) //有一個點爲必敗點,此點就爲必勝點
{
dp[pos[i]] = 1;
break;
}
}
for(int j=pos[i]-i;j>=1;j -= i) //向前移動
{
if(arr[j]>i && dp[j]==2)
{
dp[pos[i]] = 1;
break;
}
}
if(dp[pos[i]] != 1) //後繼點都爲必勝點
dp[pos[i]] = 2;
}
for(int i=1;i<=n;++i)
{
if(dp[i]==1) cout<<'A';
else cout<<'B';
}
return 0;
}