1. 程式人生 > 其它 >【CF】【博弈論】C. Permutation Game

【CF】【博弈論】C. Permutation Game

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;
}