视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
codeforcesRound#260(div2)D解题报告
2020-11-09 08:01:20 责编:小采
文档


解法:

首先存这些字符,用trie来存,通过trie就很容易联想到树型DP,这里的DP就不是取最优值之类的了,而是用来弄到达某个节点的胜负情况。

我们首先设节点v,win[v]代表已经组装好的字符刚好匹配到v了,然后需要进行下一步匹配时,先手是否可以赢,lose[v]则代表先手是否会输。

叶节点,win[v] = false, lose[v] = true.

其他节点 win[v] = win[v] | !win[child], lose[v] = lose[v] | !lose[child]. (因为每次赢的人,下一个就不是先手,所以结果肯定是跟下一个节点的赢成对立关系)。


如若win[0] = true , lose[0] = true则意味着第一局的人可以操控结果,否则按照k的次数来判断是否可以赢。

代码:

#include 
#include 
#define N_max 123456
#define sigma_size 26

using namespace std;

bool win[N_max], lose[N_max];
int n, k;
char st1[N_max];

class Trie{
public:
	int ch[N_max][sigma_size];
	int sz;

	Trie() {
	sz=0;
	memset(ch[0], 0, sizeof(ch[0]));
	}

	int idx(char c) {
	return c-'a';
	}

	void insert(char *s) {
	int l = strlen(s), u = 0;

	for (int i = 0; i < l; i++) {
	int c = idx(s[i]);

	if (!ch[u][c]) {
	ch[u][c] = ++sz;
	memset(ch[sz], 0, sizeof(ch[sz]));
	}

	u = ch[u][c];
	}
	}
};

Trie T;

void init() {
	scanf("%d%d", &n, &k);
	for (int i = 1; i <= n; i++) {
	scanf("%s", st1);
	T.insert(st1);
	}
}

void dfs(int v) {
	bool is_leaf = true;

	win[v] = false;
	lose[v] = false;

	for (int i = 0; i < sigma_size; i++) {
	int tmp = T.ch[v][i];

	if (tmp) {
	is_leaf = false;
	dfs(T.ch[v][i]);
	win[v] |= !win[T.ch[v][i]];
	lose[v] |= !lose[T.ch[v][i]];
	}
	}

	if (is_leaf) {
	win[v] = false;
	lose[v] = true;
	}
}

void ans(bool res) {
	puts(res? "First":"Second");
}

void solve() {
	dfs(0);

	if (win[0] && lose[0])
	ans(true);
	else if (win[0])
	ans(k&1);
	else
	ans(0);
}

int main() {
	init();
	solve();
}

下载本文
显示全文
专题