Codeforces Round #260(Div2) Problem D. A Lot of Games

来源:互联网 发布:篮球火 知乎 编辑:程序博客网 时间:2024/06/15 06:13
D. A Lot of Games
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

Andrew, Fedor and Alex are inventive guys. Now they invent the game with strings for two players.

Given a group of n non-empty strings. During the game two players build the word together, initially the word is empty. The players move in turns. On his step player must add a single letter in the end of the word, the resulting word must be prefix of at least one string from the group. A player loses if he cannot move.

Andrew and Alex decided to play this game k times. The player who is the loser of the i-th game makes the first move in the (i + 1)-th game. Guys decided that the winner of all games is the player who wins the last (k-th) game. Andrew and Alex already started the game. Fedor wants to know who wins the game if both players will play optimally. Help him.

Input

The first line contains two integers, n and k (1 ≤ n ≤ 1051 ≤ k ≤ 109).

Each of the next n lines contains a single non-empty string from the given group. The total length of all strings from the group doesn't exceed 105. Each string of the group consists only of lowercase English letters.

Output

If the player who moves first wins, print "First", otherwise print "Second" (without the quotes).

题解:博弈题,比赛的时候连跪两发,赛后经提醒才发现坑点,真是脑洞太小啊T_T

很明显可以发现每一个子游戏是基本独立的,那么只要搞清楚每一个子游戏的先手会赢还是输,最后将K个子游戏合并就可以知道最后的状态了。子游戏的状态可以在Trie上进行SG值判定得到。

一开始的想法是,每个子游戏的状态是两种:1.先手必胜2.先手必败,后来朱神说,要是赢了一个子游戏会导致输掉整个游戏,那先手也可以选择输掉这个子游戏。

所以这样的话一个子游戏的状态可以分为四种

1.先手可以选择赢,也可以选择输。这样整个游戏胜者毕为先手。

2.先手只能赢这样整个游戏胜者随K不断交替。

3.先手只能输。这样整个游戏胜者毕为后手。

4.先手不能选择自己的胜负。这样整个游戏胜者毕为后手。

分析完毕,挫代码献上

#include <iostream>#include <cstring>#include <cstdio>#include <cmath>#include <algorithm>#include <iomanip>#include <stack>using namespace std;#define LL long long#define MOD 1000000007struct Trie{    int next[100100][26];bool end[100100];    bool sg[100100],anti_sg[100100];    int root,L;    int newnode()    {        for(int i = 0;i < 26;i++)            next[L][i] = -1;        L++;        end[L-1]=true;        sg[L-1]=0;        anti_sg[L-1]=0;        return L-1;    }    void init()    {        L = 0;        root = newnode();    }    void search(int now)    {    if (end[now])    {    sg[now]=0;    anti_sg[now]=1;    return ;    }    for (int i=0;i<26;i++)    {    if (next[now][i]!=-1) {search(next[now][i]);if (sg[next[now][i]]==0) sg[now]=1;if (anti_sg[next[now][i]]==0) anti_sg[now]=1;}    }    }    void insert(char buf[])    {        int len = strlen(buf);        int now = root;        for(int i = 0;i < len;i++)        {            if(next[now][buf[i]-'a'] == -1)                next[now][buf[i]-'a'] = newnode();            if (end[now]) end[now]=false;            //cout<<now<<' '<<end[now]<<endl;            now = next[now][buf[i]-'a'];            //cout<<now<<' '<<buf[i]<<endl;        }    }    int query()    {    search(0);    if (sg[0]==1&&anti_sg[0]==1) return 1;    if (sg[0]==1&&anti_sg[0]==0) return 2;    if (sg[0]==0&&anti_sg[0]==1) return 3;    if (sg[0]==0&&anti_sg[0]==0) return 4;    }};Trie AC;char ch[100100];int main(){int n,k,a;while(~scanf("%d%d",&n,&k)){getchar();AC.init();for (a=1;a<=n;a++){scanf("%s",ch);AC.insert(ch);}int flag=AC.query();//cout<<flag<<endl;if (flag==1) {printf("First\n");} else if (flag==2) {if (k%2==1) printf("First\n");else printf("Second\n");}else printf("Second\n");}return 0;}


0 0
原创粉丝点击