Codeforces Round #260(Div2) Problem D. A Lot of Games
2014-08-09 14:57
369 查看
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 ≤ 105; 1 ≤ 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 1000000007
struct 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
995f
[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;
}
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 ≤ 105; 1 ≤ 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 1000000007
struct 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
995f
[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;
}
相关文章推荐
- Codeforces Round #260 (Div. 1) --B. A Lot of Games (Trie)
- codeforces content#260 D A Lot of Games
- Educational Codeforces Round 46 (Rated for Div. 2) D. Yet Another Problem On a Subsequence
- Codeforces Round #260 (Div. 2)
- Codeforces Round #260 (Div. 1) D. Serega and Fun 分块
- Codeforces Round #277.5 (Div. 2)-C. Given Length and Sum of Digits...
- Codeforces Codeforces Round #432 (Div. 2 D ) Arpa and a list of numbers
- Educational Codeforces Round 34 div2 Hungry Student Problem 简单dfs
- Codeforces Round #277.5 (Div. 2)C. Given Length and Sum of Digits...(贪心)
- Codeforces Round #170 (Div. 2) problem B
- Codeforces Round #260 (Div. 2) A. Laptops
- Codeforces Round #295 (Div. 2), problem: (A) Pangram
- Codeforces Round #320 (Div. 2) C - A Problem about Polyline
- CF 260 DIV2 D. A Lot of Games(字典树+博弈)
- Codeforces Round #437 (Div. 2, based on MemSQL Start[c]UP 3.0 - Round 2) B - Save the problem!
- Codeforces Round #437 (Div. 2 C. Ordering Pizza 贪心 only two types of pizza
- Codeforces Round #424 (Div. 2, rated, based on VK Cup Finals) Problem D (Codeforces 831D) - 贪心 - 二分答案 - 动态规划
- Codeforces Round #400 (Div. 1 + Div. 2, combined) D. The Door Problem(二分染色?/2-sat,好题)
- Codeforces Round #141 (Div. 2), problem: (D) Zigzag 线段树 整形变量注意溢出控制
- Codeforces Round #277.5 (Div. 2)-D. Unbearable Controversy of Being