博弈论全家桶

NIM博弈

裸题题意:
有n堆石子,两个绝顶聪明的人轮流操作,每次操作为取走一堆中的若干个石子,取走最后一个石子的人获胜,问先手是否能赢。

这显然是一个公平组合问题——不能行动者败。
显然,当所有堆的石子数为0,必败,此时
a[1]xora[2]xora[n]=0a[1] operatorname{xor} a[2] operatorname{xor}……a[n]=0.
不管一个人进行什么样的操作,另一个人总能把异或值调整回来。

所以如果a[1]xora[2]xora[n]0a[1] operatorname{xor} a[2] operatorname{xor}……a[n] e 0
先手给后手一个a[1]xora[2]xora[n]=0a[1] operatorname{xor} a[2] operatorname{xor}……a[n]= 0的状态,
那么以后每次先手也总能给后手一个a[1]xora[2]xora[n]=0a[1] operatorname{xor} a[2] operatorname{xor}……a[n]= 0的状态(直到石子数为零)

综上:若a[1]xora[2]xora[n]0a[1] operatorname{xor} a[2] operatorname{xor}……a[n] e 0,先手必胜。反之,先手必败。

传送门

代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
#define g getchar()
using namespace std;
int t,n,a,b;
void qr(int &x)
{
	char c=g;x=0;
	while(!('0'<=c&&c<='9'))c=g;
	while('0'<=c&&c<='9')x=x*10+c-'0',c=g;
}
int main()
{
	qr(t);
	while(t-->0)
	{
		qr(n);qr(a);
		while(--n>0)qr(b),a^=b;
		if(a)puts("Yes");
		else puts("No");
	}
	return 0;
}

威佐夫博弈

题意:
有两堆石子,数量任意,可以不同。游戏开始由两个人轮流取石子。游戏规定,每次有两种不同的取法,一是可以在任意的一堆中取走任意多的石子;二是可以在两堆中同时取走相同数量的石子。最后把石子全部取完者为胜者。现在给出初始的两堆石子的数目,如果轮到你先取,假设双方都采取最好的策略,问最后你是胜者还是败者。

前置知识:Beatty 定理

内容:
aba、b是正无理数且 1a+1b=1dfrac{1}{a} +dfrac{1}{b} =1。P={attN+}Q={bttN+}P={ lfloor{at} floor | tin N+},Q={ lfloor{bt} floor | tin N+},则PQP与QN+N+的一个划分,即PQP∩Q为空集且PQN+P∪Q为正整数集合N+

证明

  1. PQab1a+1b=1任一个正整数至多在集合P或Q中出现一次 因为a、b为正且 dfrac{1}{a} +dfrac{1}{b} =1,ab>1a、b>1tatb所以对于不同的正整数t,lfloor{at} floor各不相同,类似对b有相同的结果。PQ因此任一个整数至多在集合P或Q中出现一次。
  2. PQ()kPQmn使ma=nb=kk<manb<k+1现证明P∩Q为空集:(反证法)假设k为P∩Q的一个正整数,则存在正整数m、n 使得lfloor{ma} floor=lfloor{nb} floor=k。即k < ma、nb<k+1,等价地改写不等式为 mk+1<1a<mknk+1<1b<nkdfrac{m}{k+1}< dfrac{1}{a} < dfrac{m}{k}及dfrac{n}{k+1}< dfrac{1}{b} < dfrac{n}{k}。相加起来得
    m+nk+1<1<m+nkk<m+n<k+1mnPQ.dfrac{m+n}{k+1} < 1 <dfrac{m+n}{k} ,即 k < m+n < k+1。这与m、n为整数有矛盾,所以P∩Q为空集.
  3. N+=PQ:现证明N+=P∪Q:
    PQN+N+PQ已知P∪Q是N+的子集,剩下来只要证明N+是P∪Q的子集。
    ()kN+kPQ(反证法)假设存在kin N+且k otin P∪Q ,
    mn使ma<k<(m+1)anb<k<(n+1)b则存在正整数m、n使得lfloor{ma} floor<k <lfloor{(m+1)a} floor、lfloor{nb} floor< k <lfloor{(n+1)b} floor
    ma<k(m+1)a1<(m+1)a1anb<k(n+1)b1<(n+1)b1由此得ma < k lelfloor{ (m+1)a} floor-1<(m+1)a -1(因为a是无理数),类似地有nb < k le lfloor{ (n+1)b} floor-1<(n+1)b -1。
    mk<1a<m+1k+1nk<1b<n+1k+1m+nk<1<m+n+2k+1m+n<k<k+1<m+n+2m,n,k等价地改写为 dfrac{m}{k} < dfrac{1}{a}< dfrac{m+1}{k+1}及 dfrac{n}{k} < dfrac{1}{b}< dfrac{n+1}{k+1}。两式加起来,得 dfrac{m+n}{k} < 1 < dfrac{m+n+2}{k+1} ,即m+n < k < k+1 < m+n+2。这与m, n, k皆为正整数矛盾。

设两堆石头个数为x,y(xy)x,y(xle y).
则必败态如下:

xx yy
0 0
1 2
3 5
4 7
6 10
8 13
…… ……

可以发现xi+i=yix_i+i=y_i,XYBeattyX,Y为Beatty序列.
首先,简单证明一下必败的充分性:
xi,yi,xiyixi对于x_i,y_i,令x_i减小或y_i减小或x_i同时减小相同的值都不能到达其他必败态。

xi=ai,yi=bi(1a+1b=1)x_i=lfloor{a*i} floor,y_i=lfloor{b*i} floor(dfrac{1}{a} +dfrac{1}{b} =1)(满足Beatty定理)
因为xi+i=yix_i+i=y_i
ai+i=bilfloor{ai+i} floor=lfloor{b*i} floor
(a+1)i=bilfloor{(a+1)*i} floor=lfloor{b*i} floor
所以a+1=ba+1=b.
代入1a+1b=1dfrac{1}{a} +dfrac{1}{b} =1,可得a=5+12a=dfrac{sqrt5+1}{2}
所以我们就可以得到通项公式了。

传送门
代码:

#include<cstdio>
#include<algorithm>
using namespace std;
int main() {
	int x,y,a;
	while(~scanf("%d%d",&x,&y)) {
		if(x>y)swap(x,y);
		a=(y-x)*1.6180339887498948482045868343656;
		putchar((x!=a)+'0');puts("");
	}
	return 0;
}

未完待续……

原文地址:https://www.cnblogs.com/zsyzlzy/p/12373879.html