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


http://codeforces.com/problemset/problem/456/d
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).
Examples
input
Copy
2 3
a
b
output
Copy
First
input
Copy
3 1
a
b
c
output
Copy
First
input
Copy
1 2
ab
output
Copy
Second

http://kugwzk.info/index.php/archives/2307
题意:给出n个字符串,要求两人轮流对一个空串进行操作,每次在末尾添加一个字符要求添加完后字符串必须是这n个字符串中的某个字符串的前缀。当某个人无法操作视为输。假如某个人在第i轮输掉,那么它在第i+1轮就是先手,那么问在第k轮的时候是第一轮的先手还是后手胜利。
假如只有一轮,我们只需要建立字典树,然后dfs推出来必胜必败态就可以了。但是现在是第k轮的胜败。所以我们必须要考虑在这一轮赢是否是真正优的决策。
假如先手只能输的话,那么他将会一直输,所以导致第k轮也是输。即第一轮的先手必败。
假如先手只能赢的话,那么他们有任何可以选择的余地,所以第k轮的胜负和k的奇偶性有关。
假如先手可以自己决定胜利还是输的话,那么他可以输掉前k-1轮,保证第k轮自己的先手然后获胜就行了。所以是还是第一轮先手必胜。
假如先手无法决定自己胜利还是输的话,那么就相当于后手可以决定胜负,那么先手必败。因为后手一定可以做出对自己有利的决策。
现在考虑状态如何转移:假如一个状态的后继都是只能输的状态,那么这个就是只能赢的状态。
假如一个状态的后继都是只能赢的状态,那么这个就是只能输的状态。
假如一个状态的后继中存在只能输和只能赢的后继,或者是他的后继中有无法自己决策输赢的情况,那么他就是可以自己决定胜负的状态。
同理自己无法决定胜负的状态一定是后继中只有可以自己决定胜负的状态。
然后dfs一下,可以求出字典树root的状态,然后讨论一下就好了。
typedef long long ll;
int n,k;
int root,tot,Next[maxn+10][SIGMA],dp[maxn+10];
inline int newnode(){
    REP(i,0,SIGMA) Next[tot][i]=-1;
    tot++;
    return tot-1;
}
inline int get_idx(char c){
    return c-'a';
}
inline void Insert(char s[]){
    int len=strlen(s);
    int now=root;
    REP(i,0,len){
        int tmp=get_idx(s[i]);
        if(Next[now][tmp]==-1)
            Next[now][tmp]=newnode();
        now=Next[now][tmp];
    }
}
int dfs(int rt){
    dp[rt]=0;int cnt=0;
    int flag1=0,flag2=0,flag3=0,flag4=0;
    REP(i,0,SIGMA){
        if(Next[rt][i]==-1) continue;
        cnt++;
        int tmp=dfs(Next[rt][i]);
        if(tmp==1) flag1=1;         //后继有只能败
        else if(tmp==2) flag2=1;    //后继有只能胜
        else if(tmp==3) flag3=1;    //后继有可以自我决定
        else if(tmp==4) flag4=1;    //后继无法自我决定
    }
    if(!cnt) return dp[rt]=1;       //只能败
    if(flag2==1&&flag1==0&&flag3==0&&flag4==0) return dp[rt]=1;
    if(flag1==1&&flag2==0&&flag3==0&&flag4==0) return dp[rt]=2;
    if(flag1==1&&flag2==1||(flag4==1)) return dp[rt]=3;
    if(flag3==1&&flag1==0&&flag2==0&&flag4==0) return dp[rt]=4;
    return dp[rt];
}
int main()
{
    scanf("%d %d",&n,&k);
    root=newnode();
    REP(i,1,n+1){
        char s[maxn];scanf(" %s",s);
        Insert(s);
    }
    dfs(root);
    if(dp[root]==1) puts("Second");
    else if(dp[root]==2){
        if(k&1) puts("First");
        else puts("Second");
    }
    else if(dp[root]==3) puts("First");
    else puts("Second");
}

https://zepto.page/post/codeforces-456d
先把这些串直接加进空串,然后建字典树,在树上DP,从叶子回溯到根。
二进制状态有4种,00和11代表结果和k相关,10代表先手赢,01代表后手赢。
叶子对父亲的贡献异或10之后和父亲的状态或一下就好了。
int n,k,root,top,q[maxn][26];
char x[maxn];
void insert(){
    int len=strlen(x);
    int now=root;
    for (int i=0;i<len;i++){
        int temp=x[i]-'a';
        if (!q[now][temp]) q[now][temp]=++top;
        now=q[now][temp];
    }
}
int dfs(int now){
    int flag=1,ans;
    for (int i=0;i<26;i++){
        if (q[now][i]){
            flag=0;
            ans|=dfs(q[now][i])^3;
        }
    }
    if (flag) ans=1;
    return ans;
}
int main(){
    ios::sync_with_stdio(false);
    cin>>n>>k;
    for (int i=1;i<=n;i++)
        cin>>x,insert();
    int ans=dfs(root);
    if (ans==3||ans==2&&k&1) cout<<"First"<<endl;
    else cout<<"Second"<<endl;
}

https://bartholomew.cf/2018/07/07/codeforces-455b-a-lot-of-games/
易得如果此人能够有该局必胜的把握与必输的把握, 那么他必赢, 因为可以一直输再最后赢, 如果必输的就是必输局, 而如果一直赢的话就可以看 K 的奇偶性来判断, 奇数局先手赢, 偶数局后手赢!
那么我们知道先手与后手的目的都是一致的, 即那么都希望赢, 要么都希望输. 当然不会出现一个人想赢一个人想输的局面, 因为这样胜负已定, 就不是最优策略了!
我们的两遍dfs:
  1. 必胜点的条件是周围有一个必输点, 必输点的条件是周围都是必胜点
  2. 必胜点的条件是周围都是必输点, 必输点的条件是周围有一个必胜点
http://shirshamegha.blogspot.com/2016/03/theory-b.html

Labels

LeetCode (1432) GeeksforGeeks (1122) LeetCode - Review (1067) Review (882) Algorithm (668) to-do (609) Classic Algorithm (270) Google Interview (237) Classic Interview (222) Dynamic Programming (220) DP (186) Bit Algorithms (145) POJ (141) Math (137) Tree (132) LeetCode - Phone (129) EPI (122) Cracking Coding Interview (119) DFS (115) Difficult Algorithm (115) Lintcode (115) Different Solutions (110) Smart Algorithm (104) Binary Search (96) BFS (91) HackerRank (90) Binary Tree (86) Hard (79) Two Pointers (78) Stack (76) Company-Facebook (75) BST (72) Graph Algorithm (72) Time Complexity (69) Greedy Algorithm (68) Interval (63) Company - Google (62) Geometry Algorithm (61) Interview Corner (61) LeetCode - Extended (61) Union-Find (60) Trie (58) Advanced Data Structure (56) List (56) Priority Queue (53) Codility (52) ComProGuide (50) LeetCode Hard (50) Matrix (50) Bisection (48) Segment Tree (48) Sliding Window (48) USACO (46) Space Optimization (45) Company-Airbnb (41) Greedy (41) Mathematical Algorithm (41) Tree - Post-Order (41) ACM-ICPC (40) Algorithm Interview (40) Data Structure Design (40) Graph (40) Backtracking (39) Data Structure (39) Jobdu (39) Random (39) Codeforces (38) Knapsack (38) LeetCode - DP (38) Recursive Algorithm (38) String Algorithm (38) TopCoder (38) Sort (37) Introduction to Algorithms (36) Pre-Sort (36) Beauty of Programming (35) Must Known (34) Binary Search Tree (33) Follow Up (33) prismoskills (33) Palindrome (32) Permutation (31) Array (30) Google Code Jam (30) HDU (30) Array O(N) (29) Logic Thinking (29) Monotonic Stack (29) Puzzles (29) Code - Detail (27) Company-Zenefits (27) Microsoft 100 - July (27) Queue (27) Binary Indexed Trees (26) TreeMap (26) to-do-must (26) 1point3acres (25) GeeksQuiz (25) Merge Sort (25) Reverse Thinking (25) hihocoder (25) Company - LinkedIn (24) Hash (24) High Frequency (24) Summary (24) Divide and Conquer (23) Proof (23) Game Theory (22) Topological Sort (22) Lintcode - Review (21) Tree - Modification (21) Algorithm Game (20) CareerCup (20) Company - Twitter (20) DFS + Review (20) DP - Relation (20) Brain Teaser (19) DP - Tree (19) Left and Right Array (19) O(N) (19) Sweep Line (19) UVA (19) DP - Bit Masking (18) LeetCode - Thinking (18) KMP (17) LeetCode - TODO (17) Probabilities (17) Simulation (17) String Search (17) Codercareer (16) Company-Uber (16) Iterator (16) Number (16) O(1) Space (16) Shortest Path (16) itint5 (16) DFS+Cache (15) Dijkstra (15) Euclidean GCD (15) Heap (15) LeetCode - Hard (15) Majority (15) Number Theory (15) Rolling Hash (15) Tree Traversal (15) Brute Force (14) Bucket Sort (14) DP - Knapsack (14) DP - Probability (14) Difficult (14) Fast Power Algorithm (14) Pattern (14) Prefix Sum (14) TreeSet (14) Algorithm Videos (13) Amazon Interview (13) Basic Algorithm (13) Codechef (13) Combination (13) Computational Geometry (13) DP - Digit (13) LCA (13) LeetCode - DFS (13) Linked List (13) Long Increasing Sequence(LIS) (13) Math-Divisible (13) Reservoir Sampling (13) mitbbs (13) Algorithm - How To (12) Company - Microsoft (12) DP - Interval (12) DP - Multiple Relation (12) DP - Relation Optimization (12) LeetCode - Classic (12) Level Order Traversal (12) Prime (12) Pruning (12) Reconstruct Tree (12) Thinking (12) X Sum (12) AOJ (11) Bit Mask (11) Company-Snapchat (11) DP - Space Optimization (11) Dequeue (11) Graph DFS (11) MinMax (11) Miscs (11) Princeton (11) Quick Sort (11) Stack - Tree (11) 尺取法 (11) 挑战程序设计竞赛 (11) Coin Change (10) DFS+Backtracking (10) Facebook Hacker Cup (10) Fast Slow Pointers (10) HackerRank Easy (10) Interval Tree (10) Limited Range (10) Matrix - Traverse (10) Monotone Queue (10) SPOJ (10) Starting Point (10) States (10) Stock (10) Theory (10) Tutorialhorizon (10) Kadane - Extended (9) Mathblog (9) Max-Min Flow (9) Maze (9) Median (9) O(32N) (9) Quick Select (9) Stack Overflow (9) System Design (9) Tree - Conversion (9) Use XOR (9) Book Notes (8) Company-Amazon (8) DFS+BFS (8) DP - States (8) Expression (8) Longest Common Subsequence(LCS) (8) One Pass (8) Quadtrees (8) Traversal Once (8) Trie - Suffix (8) 穷竭搜索 (8) Algorithm Problem List (7) All Sub (7) Catalan Number (7) Cycle (7) DP - Cases (7) Facebook Interview (7) Fibonacci Numbers (7) Flood fill (7) Game Nim (7) Graph BFS (7) HackerRank Difficult (7) Hackerearth (7) Inversion (7) Kadane’s Algorithm (7) Manacher (7) Morris Traversal (7) Multiple Data Structures (7) Normalized Key (7) O(XN) (7) Radix Sort (7) Recursion (7) Sampling (7) Suffix Array (7) Tech-Queries (7) Tree - Serialization (7) Tree DP (7) Trie - Bit (7) 蓝桥杯 (7) Algorithm - Brain Teaser (6) BFS - Priority Queue (6) BFS - Unusual (6) Classic Data Structure Impl (6) DP - 2D (6) DP - Monotone Queue (6) DP - Unusual (6) DP-Space Optimization (6) Dutch Flag (6) How To (6) Interviewstreet (6) Knapsack - MultiplePack (6) Local MinMax (6) MST (6) Minimum Spanning Tree (6) Number - Reach (6) Parentheses (6) Pre-Sum (6) Probability (6) Programming Pearls (6) Rabin-Karp (6) Reverse (6) Scan from right (6) Schedule (6) Stream (6) Subset Sum (6) TSP (6) Xpost (6) n00tc0d3r (6) reddit (6) AI (5) Abbreviation (5) Anagram (5) Art Of Programming-July (5) Assumption (5) Bellman Ford (5) Big Data (5) Code - Solid (5) Code Kata (5) Codility-lessons (5) Coding (5) Company - WMware (5) Convex Hull (5) Crazyforcode (5) DFS - Multiple (5) DFS+DP (5) DP - Multi-Dimension (5) DP-Multiple Relation (5) Eulerian Cycle (5) Graph - Unusual (5) Graph Cycle (5) Hash Strategy (5) Immutability (5) Java (5) LogN (5) Manhattan Distance (5) Matrix Chain Multiplication (5) N Queens (5) Pre-Sort: Index (5) Quick Partition (5) Quora (5) Randomized Algorithms (5) Resources (5) Robot (5) SPFA(Shortest Path Faster Algorithm) (5) Shuffle (5) Sieve of Eratosthenes (5) Strongly Connected Components (5) Subarray Sum (5) Sudoku (5) Suffix Tree (5) Swap (5) Threaded (5) Tree - Creation (5) Warshall Floyd (5) Word Search (5) jiuzhang (5)

Popular Posts