巴什博奕
两个人,n个石子,每次可以取1-m个石子,不能拿的人失败,另一个人胜利
- 1 <= 石子数量 <= m 时,先手必胜
- m + 1 = 石子数量 时,先手必败
- m + 2 <= 石子数量 <= 2 * m 时,先手可以让石子数量变为 m + 1 先手必胜
推广可得
- 当n = k * (m + 1) + r
先手拿走r个,每次都可以让另一个人面对k * (m + 1)的棋局,直到k = 1。所以先手必胜
- 当n = k * (m + 1)
无论先手拿几个,后手每次都可以让先手面对k * (m + 1)的棋局,直到k = 1。所以先手必败
#include<bits/stdc++.h>
using namespace std;
int t,n,m;
int main()
{
cin >> t;
while(t -- )
{
cin >> n >> m;
if(n % (m + 1) == 0)cout << "second" << endl;
else cout << "first" << endl;
}
return 0;
}
斐波那契博奕
一堆石子,先取者可以任意取,但是不能取完,以后每个人取得石子数都不能超过上个人的两倍
先手必败,当且仅当石子数为斐波那契数时
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
long long feb[100]={0,1};
int n;
int main()
{
for(int i = 2;i <= 100; ++ i)
{
feb[i] = feb[i - 1]+feb[i - 2];
}
//cout << feb[100] << endl;
while(cin >> n && n)
{
if(binary_search(feb,feb + 100,n))cout << "Second win" << endl;
else cout << "First win" <<endl;
}
return 0;
}
威佐夫博弈
有两堆石子,每次可以从一堆石子中取任意多的石子,或者从两堆石子中取同样多的石子,不能取的人输
两堆石子(x , y)(x < y),先手必败,当且仅当
(
y
−
x
)
×
(
1
+
5
)
÷
2
=
x
(y - x)\times(1+\sqrt{5})\div2=x
(y−x)×(1+5)÷2=x
#include<bits/stdc++.h>
using namespace std;
int a,b;
int main()
{
double t=(1.0+sqrt(5))/2;
while(cin >> a >> b)
{
if(b < a)swap(a,b);
if((int)((b - a) * t) == a)cout << 0 <<endl;
else cout << 1 << endl;
}
return 0;
}
尼姆博奕
有n堆石子,两个人可以从任意一堆石子中拿任意多个石子(不能不拿),没法拿的失败
当n堆石子数量异或和为0时,先手必败。
当n堆石子数量异或和不为0,可以某一个数减去n-1堆石子数量异或和,先手必胜。
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5;
int ans,cnt,arr[N],m;
int main()
{
while(cin >> m && m)
{
ans = cnt = 0;
for(int i = 0;i < m; ++ i)
{
cin >> arr[i];
ans ^= arr[i];
}
if(ans == 0)cout << 0 <<endl;
else
{
for(int i = 0;i < m; ++ i)
{
int t = ans ^ arr[i];//求n-1堆石子的异或和,一个数字被异或和两次,相当于没有参加运算。一个数异或2次得0,0异或任何值都为它本身
if(arr[i] >= t)cnt ++ ;//如果可以减,方案加一
}
cout << cnt <<endl;
}
}
return 0;
}