Codeforces Round #260 (Div. 2) D SG函数(制胜 + 制败)

题目:A Lot Of Games

题意:给你一个有好多串的集合。一个字符串开始是空的,A和B两个人轮流在字符串后面加一个字符,保证得到的新字符串至少是集合的某一个串的前缀,谁不能加字母谁输。玩K局这个游戏,每局的输者是下一局的先手,问第K局谁赢?

题解:这个题当时只想到构造一颗前缀树,对前缀数进行SG函数的预处理,求出局势的情况。然后就是各种wa,不知道问题所在。比赛完有大神说要求先手制败,先手主动认输要下一局先手权。当时没想到啊……今天构造制败的时候,就是把所有初始化的0改成1。

代码:

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <queue>
#include <stack>
#include <vector>
#include <set>
#include <string>
using namespace std;
#define For(i,a) for(i=0;i<a;i++)
#define Foru(i,a,b) for(i=a;i<=b;i++)
#define Ford(i,a,b) for(i=a;i>=b;i--)
#define clr(ar,vel) memset(ar,vel,sizeof(ar))
#define PB push_back
#define maxint 0x7fffffff
struct node {
	int vel;
	int nex[26];
};
node s[500010];
int dfs(int x){
	int end = 0;
	for(int i = 0; i < 26; i ++) {
		if( s[x].nex[i] != -1) dfs(s[x].nex[i]), end ++;
	}
	if( end == 0) {
		s[x].vel = 0;
		return 0;
	}
	int vel = 1;
	for(int i = 0; i < 26; i ++){
		int w = s[x].nex[i];
		if( w != -1){
			vel &= s[w].vel;
		}
	}
	s[x].vel = vel^1;
	return s[x].vel;
}
int dfs2(int x){
//	cout << x << endl;
	int end = 0;
	for(int i = 0; i < 26; i ++) {
//		cout << "s[].nex   " << s[x].nex[i] << endl;
		if( s[x].nex[i] != -1) dfs2(s[x].nex[i]), end ++;
	}
	if( end == 0) {
		s[x].vel = 1;
		return s[x].vel;
	}
	int vel = 1;
	for(int i = 0; i < 26; i ++){
		int w = s[x].nex[i];
		if( w != -1){
			vel &= s[w].vel;
		}
	}
	s[x].vel = vel^1;
	return s[x].vel;
}
int main(){
	string str;
	int n, k, cnt;
	while( cin >> n >> k){
		
		memset(s, -1, sizeof(s));
		cnt = 1;
		for(int i = 0; i < n; i ++){
			cin >> str;
			int head = 0;
			for(int i = 0; i < str.length(); i++){
				int w = str[i] - 'a';
				if( s[head].nex[w] == -1) {
//					cout << "cnt " << cnt << endl;
					s[head].nex[w] = cnt;
					cnt ++;
				}
				head = s[head].nex[w];
			}
		}
		int d1 = dfs(0);
		int d2 = dfs2(0);
//		cout << d1 << ' ' << d2 << endl;
		if( d1 && d2) cout << "First" << endl;
		else if( d1 ){
			if( k%2 ) cout << "First" << endl;
			else cout << "Second" << endl;
		}
		else {
			cout << "Second" << endl;
		}
	}
				
		
	return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值