博弈论练习

版权声明:https://blog.csdn.net/huashuimu2003 https://blog.csdn.net/huashuimu2003/article/details/86348478

[cf] 石江豪pk李震p2002 SG函数

题目

http://codeforces.com/contest/603/problem/C

描述 Description
题目背景
石江豪最近爱上了一款叫《转熊英兽魔:说穿石路》(Tuhaos of China:Cardpackage)的游戏,这周的乱斗模式十分带感,规则是不会限制场上随从的数量。于是,他找到了李震,想和李震进行一次PK,而李震作为一个竞技游戏大神表示很愿意吊打他。不幸的是,他们的对战陷入了僵局。
鏖战了无数分钟之后进入了残局,石江豪和李震都已经获得了10个法力水晶,场上有n个随从,而且他们都是白板,第i个随从的生命值为ai。他们的牌库都打光了,手上只有隐藏职业的两个神秘法术,两个法术的效果分别是这样的:
1.熔岩爆裂,3费,对一个随从造成一点伤害,冻结所有随从,并将该牌洗入你的牌库。过载(7)
2.转生,2费,消灭一个血量为偶数的随从,然后召唤k个血量为被消灭随从一半的随从,然后在下回合将所有随从的攻击力降为0,并将该牌洗入你的牌库。过载(7)
不幸的是,他们两个的血量都被打成1了,而且都没有装备武器,这也就意味着,每个人在每轮都必须而且只能释放一个法术,而且,如果某人击杀了最后一个随从,他的对手会因为疲劳而炸掉,从而获得胜利。
现在轮到石江豪了,由于上回合他所使用的闪电风暴的过载效果,本回合也只剩3点法力水晶了,李震是大神级人物,当然能算出来每一轮该怎么打,而石江豪就不一样了,他想请问学编程的你,在此局面下,他是否有必胜的机会呢?
输入格式 Input Format
第一行两个整数,分别代表n和k。
第二行n个整数,第i个数代表ai。
输出格式 Output Format
如果石江豪有必胜的策略教李震做人,输出“DaDeBuCuo”。
如果石江豪必然败在李震大神手下,输出“WoHenBaoQian”。
样例输入 Sample Input
2 1
3 4
==========
1 2
3
样例输出 Sample Output
DaDeBuCuo
============
WoHenBaoQian
时间限制 Time Limitation
1s
注释 Hint
数据范围:
对于30%的数据,n≤10,k≤5,ai≤20。
对于100%的数据,1≤n≤100000,1≤k≤1000000000,1≤ai≤1000000000。
来源 Source
来源:
Codeforces Round #334 Div.1 Problem C(603C) Lieges of Legendre
数据生成:闵梓轩

真心觉得这个题面比原来的棒

题解

分别讨论k是偶数和奇数的情况。

如果k是偶数

当选择2时,有k个n个石子的小堆,状态的SG函数显然为 f n x o r k = 0 f(n)xor自身k次=0
此时我们可以计算得出 f 0..4 = 0 , 1 , 2 , 0 , 1 f(0..4)=(0,1,2,0,1) ,并且
可证明 n > = 2 f 2 n 1 = 0 f 2 n = 1 对于n>=2,有f(2n-1)=0,f(2n)=1 ,化简得 f n = 1 ( n M O D 2 ) f(n)=1-(nMOD2) ,或 f n = n 1 x o r 1 f(n)=n 按位与 1 xor 1
对于 f 2 n 1 f(2n-1) ,我们只能移动到 2 n 2 2n-2 个石子的状态(游戏1),又 f 2 n 2 = 1 > 0 f(2n-2)=1>0 ,所以 f 2 n 1 = m e x 1 = 0 f(2n-1)=mex(1)=0
对于 f 2 n f(2n) ,可以移动到 2 n 1 2n-1 的状态(游戏1),或者游戏2,游戏1和2的sg函数值都为0,所以 f 2 n = m e x 0 = 1 f(2n)=mex(0)=1

如果k是奇数

此时对于2n个石子的石堆,状态的SG函数为 f n x o r k = f n f(n)xor自身k次=f(n)
推导出 f 0..5 = 0 , 1 , 0 , 1 , 2 , 0 f(0..5)=(0,1,0,1,2,0)
可证明 n > = 2 f 2 n > 0 f 2 n + 1 = 0 对于n>=2,f(2n)>0,f(2n+1)=0
对于 f 2 n + 1 2 n f 2 n > 0 f 2 n + 1 = 0 f(2n+1),我们只能移动到2n,有f(2n)>0,所以f(2n+1)=0
对于 f ( 2 n ) f(2n) ,可以移动到 2 n 1 f 2 n 1 = 0 f 2 n > 0 2n-1,f(2n-1)=0,所以f(2n)>0
f 2 n = m e x f 2 n 1 , f n = m e x 0 , f n f(2n)=mex(f(2n-1),f(n))=mex(0,f(n)) 递归计算即可。

代码

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
inline int read()
{
	int f=1,num=0;
	char ch=getchar();
	while (!isdigit(ch)) { if (ch=='-') f=-1; ch=getchar(); }
	while (isdigit(ch)) num=(num<<1)+(num<<3)+(ch^48), ch=getchar();
	return num*f;
}
int f[]={0,1,0,1,2};
inline int odd(int x)
{
	if (x<=4) return f[x];
	if (x&1) return 0;
	return odd(x/2)==1?2:1;
}
inline int even(int x)
{
	if (x<=2) return x;
	else return x&1^1;
}
int main()
{
	int n=read(),k=read(),ans=0;
	for (int i=1;i<=n;++i)
	{
		int a=read();
		if (k&1) ans^=odd(a);
		else ans^=even(a);
	}
	puts(ans?"DaDeBuCuo":"WoHenBaoQian");
//	puts(ans?"Kevin":"Nicky");
	return 0;
}

猜你喜欢

转载自blog.csdn.net/huashuimu2003/article/details/86348478