NIM博弈
裸题题意:
有n堆石子,两个绝顶聪明的人轮流操作,每次操作为取走一堆中的若干个石子,取走最后一个石子的人获胜,问先手是否能赢。
这显然是一个公平组合问题——不能行动者败。
显然,当所有堆的石子数为0,必败,此时
a[1]xora[2]xor……a[n]=0.
不管一个人进行什么样的操作,另一个人总能把异或值调整回来。
所以如果a[1]xora[2]xor……a[n]�=0,
先手给后手一个a[1]xora[2]xor……a[n]=0的状态,
那么以后每次先手也总能给后手一个a[1]xora[2]xor……a[n]=0的状态(直到石子数为零)
综上:若a[1]xora[2]xor……a[n]�=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 定理
内容:
设a、b是正无理数且 a1+b1=1。记P={⌊at⌋∣t∈N+},Q={⌊bt⌋∣t∈N+},则P与Q是N+的一个划分,即P∩Q为空集且P∪Q为正整数集合N+。
证明
- 任一个正整数至多在集合P或Q中出现一次因为a、b为正且a1+b1=1,则a、b>1,所以对于不同的正整数t,⌊at⌋各不相同,类似对b有相同的结果。因此任一个整数至多在集合P或Q中出现一次。
- 现证明P∩Q为空集:(反证法)假设k为P∩Q的一个正整数,则存在正整数m、n使得⌊ma⌋=⌊nb⌋=k。即k<ma、nb<k+1,等价地改写不等式为 k+1m<a1<km及k+1n<b1<kn。相加起来得
k+1m+n<1<km+n,即k<m+n<k+1。这与m、n为整数有矛盾,所以P∩Q为空集.
- 现证明N+=P∪Q:
已知P∪Q是N+的子集,剩下来只要证明N+是P∪Q的子集。
(反证法)假设存在k∈N+且k∈/P∪Q,
则存在正整数m、n使得⌊ma⌋<k<⌊(m+1)a⌋、⌊nb⌋<k<⌊(n+1)b⌋
由此得ma<k≤⌊(m+1)a⌋−1<(m+1)a−1(因为a是无理数),类似地有nb<k≤⌊(n+1)b⌋−1<(n+1)b−1。
等价地改写为km<a1<k+1m+1及kn<b1<k+1n+1。两式加起来,得km+n<1<k+1m+n+2,即m+n<k<k+1<m+n+2。这与m,n,k皆为正整数矛盾。
设两堆石头个数为x,y(x≤y).
则必败态如下:
x |
y |
0 |
0 |
1 |
2 |
3 |
5 |
4 |
7 |
6 |
10 |
8 |
13 |
…… |
…… |
可以发现xi+i=yi,X,Y为Beatty序列.
首先,简单证明一下必败的充分性:
对于xi,yi,令xi减小或yi减小或xi同时减小相同的值都不能到达其他必败态。
设xi=⌊a∗i⌋,yi=⌊b∗i⌋(a1+b1=1)(满足Beatty定理)
因为xi+i=yi
即⌊ai+i⌋=⌊b∗i⌋
⌊(a+1)∗i⌋=⌊b∗i⌋
所以a+1=b.
代入a1+b1=1,可得a=25+1
所以我们就可以得到通项公式了。
传送门
代码:
#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;
}
未完待续……