题意:两个人玩游戏,每次添一个字母,不能添的为输。输的在下一局中先手。问第k局谁赢。
挺简单的一道树形题,从后往前递推,判断初始点能不能输,能不能赢。
若不能赢,则先手一直输下去。
若可以赢,则看能不能输:
若能输,则先手赢(前k-1局一直输,第k局反杀);
若不能输,则看局数,奇数局先手赢,偶数局后手赢。
代码:
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <string>
#include <cstring>
#include <cmath>
#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <queue>
#include <stack>
#include <bitset>
#include <functional>
#include <sstream>
#include <iomanip>
#include <cmath>
#include <cstdlib>
#include <ctime>
typedef long long ll;
//#pragma comment(linker, "/STACK:1024000000,1024000000") //手动扩栈
#define INF 1e9
#define maxn 110000
#define maxm 100086+10
#define mod 1000000007
#define eps 1e-7
#define PI acos(-1.0)
#define rep(i,n) for(int i=0;i<n;i++)
#define rep1(i,n) for(int i=1;i<=n;i++)
#define scan(n) scanf("%d",&n)
#define scanll(n) scanf("%I64d",&n)
#define scan2(n,m) scanf("%d%d",&n,&m)
#define scans(s) scanf("%s",s);
#define ini(a) memset(a,0,sizeof(a))
#define out(n) printf("%d\n",n)
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
bool canWin[maxn],canLose[maxn];
struct Trie
{
int ch[maxn][26];
int sz;
Trie(){ init(); }
void init()
{
sz = 1; memset(ch[0],0,sizeof(ch[0]));
}
int idx(char c) { return c - 'a'; }
void insert(char *s)
{
int u = 0, n = strlen(s);
rep(i,n)
{
int c = idx(s[i]);
if(!ch[u][c])
{
memset(ch[sz],0,sizeof(ch[sz]));
ch[u][c] = sz++;
}
u = ch[u][c];
}
}
void solve()
{
for(int i = sz-1; i >= 0; i--)
{
canWin[i] = false;
canLose[i] = count(ch[i],ch[i] + 26, 0) == 26;
rep(j,26)
{
if(ch[i][j] == 0) continue;
canWin[i] |= !canWin[ch[i][j]]; //canWin表示处在该点走的可以赢
canLose[i] |= !canLose[ch[i][j]]; //canLose表示处在该点走的可以输
}
}
}
}trie;
char s[maxn];
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
#endif
int n,k;
while(~scanf("%d%d",&n,&k))
{
trie.init();
rep1(i,n)
{
scans(s);
trie.insert(s);
}
trie.solve();
if(!canWin[0]) { puts("Second"); continue; } //如果先手不能赢,则他将一直输下去
if(canLose[0]) { puts("First"); continue; } //如果先手可以赢,也可以输,则他故意一直输,直到最后一局反杀
if(k & 1) puts("First"); //如果先手只能赢,则看玩的次数,奇数则先手赢,偶数则后手赢
else puts("Second");
}
return 0;
}