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;
    }
    
  • 相关阅读:
    KINavigationController使用演示例子
    基于STC12C5A的MINI3216多功能点阵时钟
    Android开发SDK接入机智云,智能家居实现APP远程控制多设备
    自定义通用dialogFragment
    获取取并下载tuku的漫画的爬虫
    Mvp快速搭建商城购物车模块
    仿360手机助手下载按钮
    Pythond 读写HDF5文件
    python tricks —— datetime 删除日期中的前导 0
    天文网站
  • 原文地址:https://www.cnblogs.com/mangoyang/p/9329415.html
Copyright © 2011-2022 走看看