CF-456D-(字典树+树上dp+博弈)

题意:http://codeforces.com/problemset/problem/456/D

两个人玩游戏。游戏是拼单词,给出了一个含有n个单词的词库。当前单词初始为空,每个人轮流给它末尾加一个字母,要求当前单词是词库中任意一个词的前缀,当某个人不能加字母了他就输。这个游戏重复k局,一局输的人下一局先手,最后一局定胜负。两个人都不蠢,求第一局先手是否能保证最后能赢,能就输出First,不能则输出Second。

思路:

应该要想到字典树,我一开始想到ac自动机(真是够了,哪有这么难)

博弈的话dp一下先确定一局里先手能否控制自己的输赢状态

最后再对k讨论一下就行了

  1 #define IOS ios_base::sync_with_stdio(0); cin.tie(0);
  2 #include <cstdio>//sprintf islower isupper
  3 #include <cstdlib>//malloc  exit strcat itoa system("cls")
  4 #include <iostream>//pair
  5 #include <fstream>//freopen("C:\\Users\\13606\\Desktop\\Input.txt","r",stdin);
  6 #include <bitset>
  7 //#include <map>
  8 //#include<unordered_map>
  9 #include <vector>
 10 #include <stack>
 11 #include <set>
 12 #include <string.h>//strstr substr strcat
 13 #include <string>
 14 #include <time.h>// srand(((unsigned)time(NULL))); Seed n=rand()%10 - 0~9;
 15 #include <cmath>
 16 #include <deque>
 17 #include <queue>//priority_queue<int, vector<int>, greater<int> > q;//less
 18 #include <vector>//emplace_back
 19 //#include <math.h>
 20 #include <cassert>
 21 #include <iomanip>
 22 //#include <windows.h>//reverse(a,a+len);// ~ ! ~ ! floor
 23 #include <algorithm>//sort + unique : sz=unique(b+1,b+n+1)-(b+1);+nth_element(first, nth, last, compare)
 24 using namespace std;//next_permutation(a+1,a+1+n);//prev_permutation
 25 //******************
 26 clock_t __START,__END;
 27 double __TOTALTIME;
 28 void _MS(){__START=clock();}
 29 void _ME(){__END=clock();__TOTALTIME=(double)(__END-__START)/CLOCKS_PER_SEC;cout<<"Time: "<<__TOTALTIME<<" s"<<endl;}
 30 //***********************
 31 #define rint register int
 32 #define fo(a,b,c) for(rint a=b;a<=c;++a)
 33 #define fr(a,b,c) for(rint a=b;a>=c;--a)
 34 #define mem(a,b) memset(a,b,sizeof(a))
 35 #define pr printf
 36 #define sc scanf
 37 #define ls rt<<1
 38 #define rs rt<<1|1
 39 typedef pair<int,int> PII;
 40 typedef vector<int> VI;
 41 typedef unsigned long long ull;
 42 typedef long long ll;
 43 typedef double db;
 44 const db E=2.718281828;
 45 const db PI=acos(-1.0);
 46 const ll INF=(1LL<<60);
 47 const int inf=(1<<30);
 48 const db ESP=1e-9;
 49 const int mod=(int)1e9+7;
 50 const int N=(int)1e5+10;
 51 
 52 int trie[N][26],tot;
 53 
 54 void insert(char s[])
 55 {
 56     int len=strlen(s);
 57     int root=0;
 58     for(int i=0;i<len;i++)
 59     {
 60         int id=s[i]-'a';
 61         if(!trie[root][id]) trie[root][id]=++tot;
 62         root=trie[root][id];
 63     }
 64 }
 65 
 66 char s[N];
 67 int dp[N][2];
 68 void dfs(int root,int c)
 69 {
 70     bool ok=0,no=0;
 71     bool ok2=1,no2=1;
 72     bool have=0;
 73     for(int i=0;i<=25;++i)
 74     {
 75         int to=trie[root][i];
 76         if(to)
 77         {
 78             have=1;
 79             dfs(to,c+1);
 80             if(dp[to][1])ok=1;
 81             if(dp[to][0])no=1;
 82             if(!dp[to][1])ok2=0;
 83             if(!dp[to][0])no2=0;
 84         }
 85     }
 86     if(!have)
 87     {
 88         if(c&1)dp[root][1]=1;
 89         else dp[root][0]=1;
 90         return ;
 91     }
 92     if(c&1)
 93     {
 94         if(ok2&&no2)
 95         {
 96             dp[root][0]=0;
 97             dp[root][1]=0;
 98         }
 99         else if(no2)
100         {
101             dp[root][0]=1;
102             dp[root][1]=0;
103         }
104         else if(ok2)
105         {
106             dp[root][0]=0;
107             dp[root][1]=1;
108         }
109     }
110     else
111     {
112         if(ok&&no)
113         {
114             dp[root][0]=1;
115             dp[root][1]=1;
116         }
117         else if(no)
118         {
119             dp[root][0]=1;
120             dp[root][1]=0;
121         }
122         else if(ok)
123         {
124             dp[root][0]=0;
125             dp[root][1]=1;
126         }
127     }
128 }
129 
130 int main()
131 {
132     int n,k;
133     sc("%d%d",&n,&k);
134     for(int i=1;i<=n;++i)
135     {
136         sc("%s",s);
137         insert(s);
138     }
139     dfs(0,0);
140     bool ok=0,no=0;
141     for(int i=0;i<=25;++i)
142     {
143         int to=trie[0][i];
144         if(to)
145         {
146             if(dp[to][1])ok=1;
147             if(dp[to][0])no=1;
148         }
149     }
150     bool ans=0;
151     if(ok&&no)
152     {
153         ans=1;
154     }
155     else if(ok)
156     {
157         if(k&1)ans=1;
158     }
159     if(ans)
160         pr("First\n");
161     else
162         pr("Second\n");
163     return 0;
164 }
165 
166 /**************************************************************************************/

 

posted @ 2020-03-28 19:55  ZMWLxh  阅读(350)  评论(0编辑  收藏  举报