Codeforces 455 B. A Lot of Games

Posted mangoyang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces 455 B. A Lot of Games相关的知识,希望对你有一定的参考价值。


(>Codeforces space 455 B. A Lot of Games<)

题目大意 : 有两个人在玩游戏,一共玩 (k) 轮,每一轮的一开始有一个空串,双方每一回合需要在空串后面加一个字符,但必须要满足加完这个字符之后的字符串是给定大小为 (n) 的母串集合中任意一个串的前缀,不能操作者输,规定第一轮的先手为第一个人,接下来每一轮的先手为上一轮的输家,规定最终的赢家是第 (k) 轮的赢家,在双方都采取最优策略的情况下,求最终的赢家是第一轮的先手还是后手.

(1 leq n leq 10^5 1 leq k leq 10^9)

解题思路 :

先单独考虑每一轮的游戏,发现本质上就是对母串建 (Trie) 树并在 (Trie) 树上每次向下移动,不能移动的输

所以可以先 (dp) 出对于 (Trie) 树上每一个节点,能获得的最终状态是怎样的.

观察发现,如果一个位置往下走既可以到必胜态又可以必败态,那么就可以通过这个位置控制下一局的先后手

进一步发现,如果某一方既可以必胜又可以必败,那么其必然能获得最终的胜利.

考虑如果子游戏中不存在这样的状态,那么如果先手必败则后手赢,如果先手必胜则胜负由 (k) 的奇偶性决定

所以只需要 (dp) 记录维护 (4) 种值,分别表示 (能必胜,能必败,既能必胜又能必败,什么都不能),枚举后继的状态转移即可



/*program by mangoyang*/
#include<bits/stdc++.h>
#define inf (0x7f7f7f7f)
#define Max(a, b) ((a) > (b) ? (a) : (b))
#define Min(a, b) ((a) < (b) ? (a) : (b))
typedef long long ll;
using namespace std;
template <class T>
inline void read(T &x){
    int f = 0, ch = 0; x = 0;
    for(; !isdigit(ch); ch = getchar()) if(ch == ‘-‘) f = 1;
    for(; isdigit(ch); ch = getchar()) x = x * 10 + ch - 48;
    if(f) x = -x;
}
#define N (1000005)
const int win = 1, lose = 2, lover = 3, fucker = 4;
char s[N];
int ch[N][26], f[N], n, k, size;
inline void insert(char *s){
    int p = 1, len = strlen(s);
    for(int i = 0; i < len; i++){
        int c = s[i] - ‘a‘;
        if(!ch[p][c]) ch[p][c] = ++size;
        p = ch[p][c];
    }
}
inline void solve(int u){
    f[u] = lose; int cwin = 0, close = 0, all = 0;
    for(int c = 0; c < 26; c++) if(ch[u][c]){
        int v = ch[u][c]; solve(v), all++;
        if(f[v] == lose) cwin = 1;
        if(f[v] == win) close = 1;
        if(f[v] == fucker) return (void) (f[u] = lover); 
    }
    if(cwin && close) return (void) (f[u] = lover);
    if(!cwin && !close && all) return (void) (f[u] = fucker);
    if(cwin) f[u] = win; if(close) f[u] = lose; 
}
int main(){
    size = 1;
    read(n), read(k);
    for(int i = 1; i <= n; i++) scanf("%s", s), insert(s);
    solve(1); 
    if(f[1] == lover) return puts("First"), 0;
    if(f[1] == fucker || f[1] == lose) return puts("Second"), 0;
    if(k & 1) puts("First"); else puts("Second");
    return 0;
}



以上是关于Codeforces 455 B. A Lot of Games的主要内容,如果未能解决你的问题,请参考以下文章

CodeForces 456D&455B--A Lot of Games(Trie+博弈)

CF455B A Lot of Games

CF455B A Lot of Games

CF455B A Lot of Games

codeforces480E Parking Lot

CodeForces 455D 分块