zoukankan      html  css  js  c++  java
  • Codeforces 455 B. A Lot of Games

    [$>Codeforces space 455 B. A Lot of Games<$](http://codeforces.com/contest/455/problem/B)

    题目大意 : 有两个人在玩游戏,一共玩 (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;
    }
    
  • 相关阅读:
    BEC listen and translation exercise 44
    中译英12
    BEC listen and translation exercise 43
    中译英11
    BEC listen and translation exercise 42
    中译英10
    BEC listen and translation exercise 41
    中译英9
    BEC listen and translation exercise 40
    中译英8
  • 原文地址:https://www.cnblogs.com/mangoyang/p/9329415.html
Copyright © 2011-2022 走看看