Codeforces contest 1033 problem C Permutation Game——SG

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), and
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”.

Examples
inputCopy
8
3 6 5 4 2 7 1 8
outputCopy
BAAAABAB
inputCopy
15
3 11 2 5 10 9 7 13 15 8 4 12 6 1 14
outputCopy
ABAAAABBBAABAAB
Note
In the first sample, if Bob puts the token on the number (not position):

1: Alice can move to any number. She can win by picking 7, from which Bob has no move.
2: Alice can move to 3 and 5. Upon moving to 5, Bob can win by moving to 8. If she chooses 3 instead, she wins, as Bob has only a move to 4, from which Alice can move to 8.
3: Alice can only move to 4, after which Bob wins by moving to 8.
4, 5, or 6: Alice wins by moving to 8.
7, 8: Alice has no move, and hence she loses immediately.

题意:

给你n个数,并定义以下规则:
1.从i 到 j 的条件是aj>ai
2.从i 到 j 的条件是|j-i|%ai==0
并且i!=j的时候ai!=aj

题解:

SG函数就是说,当终态为必输态时,终态的mex=0,mex代表{不出现在集合里的最大非负整数}。当一个状态的mex=0的时候就代表这个状态是必输态,详细证明去网上搜,因为我也不太懂,做这道题目的时候才学的。那么我们从任意一个点开始搜,如果搜不下去了就代表它是必输态,返回0,然后由于一个点可能连着多条边,那我们就用一个vector来记录,最后找他的mex就好了。

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
vector<int>vec[N];
int fin[N];
int n,a[N];
void dfs(int x)
{
    vec[x].clear();
    int flag=0;
    for(int i=1;;i++)
    {
        int pos=i*a[x]+x;
        if(pos>n)
            break;
        if(a[pos]<=a[x])
            continue;
        flag=1;
        if(fin[pos]==-1)
            dfs(pos);
        vec[x].push_back(fin[pos]);
    }
    for(int i=1;;i++)
    {
        int pos=-i*a[x]+x;
        if(pos<=0)
            break;
        if(a[pos]<=a[x])
            continue;
        flag=1;
        if(fin[pos]==-1)
            dfs(pos);
        vec[x].push_back(fin[pos]);
    }
    if(!flag)
        fin[x]=0;
    else
    {
        sort(vec[x].begin(),vec[x].end());
        unique(vec[x].begin(),vec[x].end());
        int ans=0,pos=0;
        int siz=vec[x].size();
        while(vec[x][pos]==ans&&pos<siz)
            pos++,ans++;
        fin[x]=ans;
    }
}
int main()
{
    memset(fin,-1,sizeof(fin));
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    for(int i=1;i<=n;i++)
    {
        if(fin[i]==-1)
            dfs(i);
        printf("%c",fin[i]?'A':'B');
    }
    printf("\n");
    return 0;
}

猜你喜欢

转载自blog.csdn.net/tianyizhicheng/article/details/84026160
今日推荐