After a long day, Alice and Bob decided to play a little game. The game board consists of n cells in a straight line, numbered from 1 to n, where each cell contains a number ai between 1 and n. Furthermore, no two cells contain the same number.
A token is placed in one of the cells. They take alternating turns of moving the token around the board, with Alice moving first. The current player can move from cell i
to cell j only if the following two conditions are satisfied:
- the number in the new cell j
must be strictly larger than the number in the old cell i (i.e. aj>ai
) - the distance that the token travels during this turn must be a multiple of the number in the old cell (i.e. |i−j|modai=0 ).
Whoever is unable to make a move, loses. For each possible starting position, determine who wins if they both play optimally. It can be shown that the game is always finite, i.e. there always is a winning strategy for one of the players.
Input
The first line contains a single integer n(1≤n≤105) — the number of numbers.
The second line contains n integers a1,a2,…,an (1≤ai≤n). Furthermore, there are no pair of indices i≠j such that ai=aj
.
Output
Print s — a string of n characters, where the i-th character represents the outcome of the game if the token is initially placed in the cell i. If Alice wins, then si has to be equal to “A”; otherwise, si has to be equal to “B”.
基本博弈论题目。根据题意,在数组中建立路径,尤其限定条件可知,可行的路径有限且小于 n2 ,因此建立邻接表存储可行路径。本题中容易确定其必败态,在数组中不能再移动的点,即邻接表为空的节点。
现在从位置 i 上开始移动,考虑在位置i上落子的输赢
- 存在一种方案可移动到必败
也就是说,在当前移动完成后,下一轮开始的位置一定会失败,那么对于当前这一轮来说,这一局必胜。 - 任何移动方式都不能达到必败态
无论如何移动,下一轮开始的位置都一定会赢,那么对于这一轮来说,这一局必败
根据以上的递推方式,就可以推得所有位置上的输赢。
#include <stdio.h>
#include <climits>
#include <algorithm>
#include <map>
using namespace std;
struct ListNode{
int index;
ListNode* pre;
ListNode(){}
ListNode(int i):index(i),pre(NULL){}
};
struct Head{
ListNode* p;
Head():p(NULL){}
};
inline int abs(int x){
if(x<0)
return -x;
return x;
}
int len;
int board[100240];
Head adj[100240];
map<int,bool> mapping;
bool sol(int finish);//finish : index
int main(){
scanf("%d",&len);
for(int i=1;i<=len;i++)
scanf("%d",&board[i]);
for(int i=1;i<=len;i++){
for(int j=i+board[i];j<=len;j+=board[i])
if(board[i]<board[j]){
ListNode *edge=new ListNode(j);
edge->pre=adj[i].p;
adj[i].p=edge;
}
for(int j=i-board[i];j>0;j-=board[i])
if(board[i]<board[j]){
ListNode *edge=new ListNode(j);
edge->pre=adj[i].p;
adj[i].p=edge;
}
}
for(int i=1;i<=len;i++)
if(sol(i))
printf("A");
else
printf("B");
printf("\n");
return 0;
}
bool sol(int finish){
if(mapping.find(finish)!=mapping.end())
return mapping[finish];
ListNode* next=adj[finish].p;
bool ans=false;
while(next){
ans |= !sol(next->index);
next=next->pre;
}
mapping[finish]=ans;
return ans;
}