最近在学博弈,写下威佐夫博弈的证明,巩固下对博弈的理解(奇异局势,NP状态,SG函数等)
题目大意
有两堆石子,两个人轮流取石子,有两种取法,一种是取一堆里的任意个,另一种是两堆同时取任意个,给出初始石子的数目,假设双方都采取最好的策略,问最后你是胜者还是败者。
思路分析
规定后手必胜态为奇异局势,且(0,0)为第0个奇异局势!!!。
又因为(a,b)与(b,a)是一样的,所以令(x,y)中,x<=y。
接下来的奇异局势:
显然,(0,n)不是。(1,1)也不满足。
对于(1,2),先手一次不可能取完,而无论先手怎么取,后手都能一次取完。
因此(1,2)是接下来第一个奇异局势。
考虑到由奇异局势能够转移到的局势均不是奇异局势:
因此(0,0+n)、(0+n,0+n)、(1,2+n)、(1+n,2+n)均不是奇异局势(其中n∈Z+)
所以接下来的奇异局势应该是此前所有奇异局势无法转移到的第一个局势(第一个局势的意思就是对于局势(x,y),x要尽可能小,然后y也要最小)
∴y-x的值要尽可能小
∴y-x=mex{此前所有奇异局势的y-x} (否则就能由前面的奇异局势转移得到)
由数学归纳法易得:
第n个奇异局势(x,y)的y-x=n
记第n个奇异局势为(x,x+n)。
若x在此前奇异局势的x或y中出现,那就可以由此前奇异局势转移得来,显然不成立。
而若x不在此前奇异局势的x或y中出现,那就无法由由此前奇异局势转移得来。
又∵x要最小
∴x=mex{此前奇异局势出现过的x或y}
此时,若理论上可以一项一项地手动推出所有的奇异局势了,但x时而+1,时而+2,因此通项公式却仍然难以得到。
Betty定理
如果两个无理数a,b满足:
1 a \frac{1}{a} a1+ 1 b \frac{1}{b} b1=1
那么对于两个集合A,B:
A=
{
⌊
n
a
⌋
}
\begin{Bmatrix} ⌊na⌋ \end{Bmatrix}
{⌊na⌋},B=
{
⌊
n
b
⌋
}
\begin{Bmatrix}⌊nb⌋ \end{Bmatrix}
{⌊nb⌋},n
∈
\in
∈ Z+
存在以下两个结论:
A∩B=∅,A∪B=N+
通项推导
有了Betty定理,以及上面的结论
对于奇异局势(x,x+n)
根据Betty定理,x可被表示为⌊na⌋,y可被表示为⌊na⌋+n=⌊n(a+1)⌋
∴
1
a
\frac{1}{a}
a1+
1
a
+
1
\frac{1}{a+1}
a+11=1
∴
a
2
−
a
+
1
=
0
a^2-a+1=0
a2−a+1=0
∴a=
1
+
√
5
2
\frac{1+√5}{2}
21+√5 (
1
−
√
5
2
\frac{1-√5}{2}
21−√5<1舍弃)
所以第n个奇异局势就是(
1
+
√
5
2
\frac{1+√5}{2}
21+√5n,
1
+
√
5
2
\frac{1+√5}{2}
21+√5n+n) (取下整)
int main()
{
int a,b;
while(cin >> a >> b){
if(a > b)swap(a,b);
double tmp = (1.0+sqrt(5.0))/2;
double n = b - a;
if((int)(n * tmp) == a)cout << 0 << endl;
else cout << 1 << endl;
}
return 0;
}
扩展威佐夫博弈
给你两堆石子,每次可以单独拿一堆中的任意值,或者两堆都拿,但是两堆拿的值需满足∣ x − y ∣ ≤ d (d为给定常数)
从原来的y=x+n变为了y=x+nd
那么根据Betty定理,x可被表示为⌊na⌋,y可被表示为⌊na⌋+nd=⌊n(a+d)⌋
∴
1
a
\frac{1}{a}
a1+
1
a
+
d
\frac{1}{a+d}
a+d1=1
解得a=
2
−
d
+
√
d
²
+
4
2
\frac{2-d+√d²+4}{2}
22−d+√d²+4
所以第n个奇异局势就是(
2
−
d
+
√
d
²
+
4
2
\frac{2-d+√d²+4}{2}
22−d+√d²+4n,
2
+
d
+
√
d
²
+
4
2
\frac{2+d+√d²+4}{2}
22+d+√d²+4n) (取下整)
int main() {
ll a,b,d;
int t;cin>>t;
while(t--){
cin>>a>>b>>d;
d++;
if(a>b)swap(a,b);
ll n=(b-a)/d;
double x=n*((sqrt(4.0+d*d)-d+2.0)/2.0);
double y=n*((sqrt(4.0+d*d)+d+2.0)/2.0);
if((int)x==a&&(int)y==b)cout<<0<<endl;
else cout<<1<<endl;
}
}