Codeforces 455B A Lot of Games(字典树+博弈)

题目连接: Codeforces 455B A Lot of Games

题目大意:给定n,表示字符串集合。给定k,表示进行了k次游戏,然后是n个字符串。每局开始,字符串为空串,然后两人轮流在末尾追加字符,保证新的字符串为集合中某字符串的前缀,不能操作者输,新一轮由上一句输的人先手。

解题思路:首先对字符集合建立字典树,然后根据博弈的必胜必败性质搜索出先手的决策状态,可决定胜败3,只能胜利2,只能失败1,不可掌控(即对手可决定胜败)0。

对于状态3,为必胜,可以采用前K-1场败,然后保证第K场自己先手,取必胜方案。

对于状态2,无论则们走都是赢的话,肯定是两个人轮流胜局,所以判断K的奇偶性。

对于状态1和0,必败,因为一直输,一直先手。

#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;
const int maxn = 1e5+5;

struct node {
    int val, arr[30];
    node () {
        val = 0;
        memset(arr, 0, sizeof(arr));
    }
}t[maxn*2];

int top = 1, len, n, k;
char str[maxn];

inline int get_node () {
    return top++;
}

void insert (int x, int d) {

    if (d == len)
        return;

    int mv = str[d] - ‘a‘;
    if (t[x].arr[mv] == 0)
        t[x].arr[mv] = get_node();
    insert(t[x].arr[mv], d+1);
}

int solve (int x) {

    int& ans = t[x].val;
    ans = 0;

    bool flag = true;
    for (int i = 0; i < 26; i++) {
        if (t[x].arr[i]) {
            flag = false;
            ans |= solve(t[x].arr[i]);
        }
    }

    if (flag)
        ans = 1;
    return 3-ans;
}

int main () {
    scanf("%d%d", &n, &k);

    for (int i = 0; i < n; i++) {
        scanf("%s", str);
        len = strlen(str);
        insert(0, 0);
    }

    solve(0);
    int ans = t[0].val;
    if (ans < 2)
        printf("Second\n");
    else if (ans == 2)
        printf("%s\n", k&1 ? "First" : "Second");
    else
        printf("First\n");
    return 0;
}

Codeforces 455B A Lot of Games(字典树+博弈)

时间: 2024-08-18 23:46:03

Codeforces 455B A Lot of Games(字典树+博弈)的相关文章

Codeforces 455B A Lot of Games 字典树上博弈

题目链接:点击打开链接 题意: 给定n个字符串,k局游戏 对于每局游戏,2个玩家轮流给一个空串加入一个小写字母使得加完后的字符串不是n个字符串的前缀. 输家下一轮先手 问是先手必胜还是后手必胜 思路: 对于第一局游戏,若先手能到达必败态和必胜态,则先手会一直输到倒数第二局然后最后一局必胜 所以此时是first 若先手是必胜态或者是必败态,则是轮流赢.跟k的奇偶有关 #include <cstdio> #include <cstring> #include<iostream&g

codeforces 455B A Lot of Games(博弈,字典树)

题目大意:给定n,表示字符串集合.给定k,表示进行了k次游戏,然后是n个字符串.每局开始,字符串为空串,然后两人轮流在末尾追加字符,保证新的字符串为集合中某字符串的前缀,不能操作者输,新一轮由上一句输的人先手. 解题思路:首先对字符集合建立字典树,然后根据博弈的必胜必败性质搜索出先手的决策状态,可决定胜败3,只能胜利2,只能失败1,不可掌控(即对手可决定胜败)0. 对于状态3,为必胜,可以采用前K-1场败,然后保证第K场自己先手,取必胜方案. 对于状态2,无论则们走都是赢的话,肯定是两个人轮流胜

codeforces 455B A Lot of Games (Trie + dfs)

题目大意: 两个人往一个空的字符串里填单词,每一次只能填一个,而且填完之后要是给出的N个字符串的前缀. 思路分析: 先用给出的所有单词建字典树. 然后从根节点开始dfs. win [x] 表示踩在x节点上是否有必胜策略 lose [x] 表示踩在x节点上是否有必败策略. 然后是博弈的过程. 如果先手有必胜和必败的策略,那么他可以一直输到k-1 如果只有必胜策略.那么只有当k为奇数的时候它才能赢. 其他为后手赢. #include <cstdio> #include <iostream&g

字典树+博弈 CF 455B A Lot of Games(接龙游戏)

题目链接 题意: A和B轮流在建造一个字,每次添加一个字符,要求是给定的n个串的某一个的前缀,不能添加字符的人输掉游戏,输掉的人先手下一轮的游戏.问A先手,经过k轮游戏,最后胜利的人是谁. 思路: 很显然先将n个字符串插入到字典树上,因为字典树上有分叉,不能仅仅判断字符串长度奇偶性来判断.字典树看成无环的状态图,如果按照拓扑排序逆序进行排序,在判断每个节点的时候,它的后继都已经判断过了.定义两个数组can_win[u], can_lose[u],表示u节点走下去“可能赢吗?”以及u节点走下去”可

Codeforces 514C Watto and Mechanism(字典树)

题目链接  Watto and Mechanism 题意  给出n个串(相当于字典),然后给出m个询问. 每个询问以字符串的形式给出,你需要改变这个字符串中的任意一个字符 (必须改变且只能改变一个) 如果改变之后可以成为n个串中的一个字符串,则输出YES, 否则输出NO. 字母集合为{a, b, c} 考虑字典树. 首先把n个单词插入字典树中. 询问的时候用dfs,flag表示搜索到当前是否已经改变过一个字符. 如果已经改变过那只能按照当前剩下的字符串一条路查询下去. 否则可以按老字符或新字符进

Codeforces 633 C Spy Syndrome 2 字典树

题意:还是比较好理解 分析:把每个单词反转,建字典树,然后暴力匹配加密串 注:然后我就是特别不理解,上面那种能过,而且时间很短,但是我想反之亦然啊 我一开始写的是,把加密串进行反转,然后单词正着建字典树,然后就TLE了,反着写就能过 真是百思不得解,然后我猜测可能是单词数目比较少 #include <cstdio> #include <iostream> #include <cstring> #include <cstdlib> #include <v

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

题意:给n个字符串.进行k次游戏.每局开始,字符串为空串,然后两人轮流在末尾追加字符,保证新的字符串为集合中某字符串的前缀,不能操作者输,新一轮由上一句输的人先手. 题解: #看到此题毫无头绪,队友写了神(xiang)一样的sg函数,我在旁边默默说,不太对吧,应该求必输必赢什么的,然后……然后怎样?我也不知道了…… #应该好好想想的,不应该轻易放弃啊…… 对于每个节点分成四种情况,必输,必赢,可输可赢,不可控制情况(即后手可输可赢) 当一个结点的子节点有一个必输的时候,该节点可以胜,当有一个子结

CodeForces 706D Vasiliy&#39;s Multiset (字典树查询+贪心)

题意:最开始的时候有一个集合,集合里面只有一个元素0,现在有q次操作,操作分为3种: + x: 表示向集合中添加一个元素x - x:表示删除集合中值为x的一个元素 ? x:表示查询集合中与x异或的最大值为多少 析:这是一个字典树的应用,不过确实没看出来....主要思想是这样,先用10进制数,转成二进制数,记下每个结点的0,1的个数,这样增加和删除,就是对01的删除, 剩下的就是查询,那么尽量让0和1XOR是最大的,所以,对于给定数,我们要去尽量他的XOR数,如果找到就加上,找不到,就找下一个.这

Codeforces 706D Vasiliy&#39;s Multiset(可持久化字典树)

[题目链接] http://codeforces.com/problemset/problem/706/D [题目大意] 要求实现一个集合中的三个操作,1:在集合中加入一个元素x,2:从集合中删除一个元素x(保证x存在),3:要求从集合中选出一个数,使得其与给出的数x的异或值最大,输出这个异或值. [题解] 可以将所有的以二进制形式存在01字典树上,删除即插入权值为-1的二进制串,对于异或值最大的操作,我们只要在字典树上按位贪心,从最高位开始尽量保证该位存在最后就能得到答案.写代码的时候直接写了