1. 程式人生 > >Codeforces 455 B. A Lot of Games

Codeforces 455 B. A Lot of Games

這樣的 spa 兩個 後繼 program 狀態 ace http 解題思路


\(>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