Codeforces 456 Problem D A Lot of Games

本文探讨了游戏开发中涉及的策略与算法实现,包括玩家交互、AI行为、游戏优化等核心内容。通过深入分析游戏设计中的关键元素,提供了一套优化游戏体验的技术解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

D. A Lot of Games
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

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).


题意是说给定n个字符串,两个人做k次游戏,每一次游戏的规则是,首先有一个空串,两个人轮流向串中添加字符,必须满足这个字符串是给定的n个字符串中的其中一个的前缀,如果有人不能添加字符,则说明他输了这一次,下一次游戏由输的人先手,直到k次游戏结束,如果先手赢了输出first,否则输出second;

对于先手来说,

如果先手不仅有必胜的策略,而且有必败的策略,他可以先输k-1盘,然后赢一盘就可以了,先手赢;

如果先手有必胜的策略,没有必败的策略,那么两个人轮流先手,如果有奇数盘,则先手赢,偶数盘,则后手赢;

如果只有必败的策略,那么后手可以一直让他败下去,则后手赢;

我们可以利用n个字符串建立一个Trie树,用两个数组记录先手是否有必胜态,或者必败态,拿必胜态的数组举例子,因为先手只能拿到奇数层,后手拿到偶数层,如果这个点是偶数层的,那么它的子节点是先手取,如果子节点中存在必胜态,这个节点也是必胜态。如果这个点是奇数层,子节点中存在必败态,则这个节点也是必败的。这样一直更新到根节点,得到先手是否有必胜的策略然后再判断是否有必败的策略就可以了。

#include<cstdio>
#include<cmath>
#include<cstring>
const int Maxn=100009;
int chd[Maxn][26],pre[Maxn],State[Maxn],State2[Maxn],level[Maxn];
int p,nn=1;
char str[Maxn];

void insert(char *str)
{
	p=0;
	int cnt=0;
	while(*str)
	{
		cnt++;
		int c=(*str++)-'a';
		if(!chd[p][c])
		{
			memset(chd[nn],0,sizeof(chd[nn]));
			chd[p][c]=nn++;
			
		}
		pre[chd[p][c]]=p;
		p=chd[p][c];
		level[p]=(cnt&1);
	}
	State[p]=State2[p]=(cnt&1)+1;
}

int main()
{
	
	int n,k;
	scanf("%d%d",&n,&k);
	memset(chd[0],0,sizeof(chd[0]));
	for(int i=0;i<n;i++)
	{
		scanf("%s",str);
		insert(str);
	}
	
	
	for(int i=nn-1;i>0;i--)
	{
		int u=pre[i];
		if(!State[u]) State[u]=State[i];
		else
		{
			if(level[u]&&State[i]==1) State[u]=1;
			if(!level[u]&&State[i]==2) State[u]=2;
		}
	}
	for(int i=nn-1;i>0;i--)
	{
		int u=pre[i];
		if(!State2[u]) State2[u]=State2[i];
		else
		{
			if(!level[u]&&State2[i]==1) State2[u]=1;
			if(level[u]&&State2[i]==2) State2[u]=2;
		}
	}
	        
    
	if(State[0]==2)
	{
		if(State2[0]==1) printf("First\n");
		else 	
		{
			printf("%s\n", (k & 1) ? "First" : "Second");
		}
	}
	else printf("Second\n");
	
	return 0;
} 


### 关于Codeforces中的GCD问题 在Codeforces平台上存在多个涉及最大公约数(GCD)概念的问题。其中一道具有代表性的题目是编号为1025B的“Weakened Common Divisor”,该题由著名数学家Ildar引入了一个新的概念——弱化公因数(WCD),即对于一系列整数对列表而言的一种特殊性质[^2]。 具体到这道题目的描述如下:给出一个长度为\(n\)的数组\(a\),目标是在所有元素上加上同一个常量\(d\)之后能够找到至少两个不同的位置其值的最大公约数大于等于2,并且要使这个加上的常量尽可能小。此题的关键在于通过计算相邻两数之差来间接获取可能存在的公共因子,进而利用这些信息推导出满足条件所需的最小增量\[d\][^4]。 为了高效解决这类基于GCD的问题,在算法设计方面通常会采用一些特定技巧: - **差分遍历**:通过对原始序列做适当变换简化问题结构; - **快速求解GCD**:借助欧几里得算法迅速定位潜在候选者; - **优化查找过程**:针对所得结果进一步筛选最优方案; 下面是一个Python版本的解决方案片段用于演示如何处理上述提到的任务逻辑: ```python from math import gcd from itertools import pairwise def min_operations_to_weak_gcd(nums): diff_gcd = 0 for prev, curr in pairwise(nums): diff_gcd = gcd(diff_gcd, abs(curr - prev)) if diff_gcd == 1: return -1 factors = get_factors(diff_gcd) result = float('inf') target_modulo = nums[0] % diff_gcd for factor in factors: candidate = ((target_modulo + diff_gcd - (nums[0] % factor)) % factor) result = min(result, candidate) return int(result) def get_factors(n): """Helper function to generate all divisors.""" res = [] i = 1 while i*i <= n: if n % i == 0: res.append(i) if i != n // i: res.append(n//i) i += 1 return sorted(res)[::-1] ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值