Part1.威佐夫博弈
题目主要背景
有两堆石子,数量任意,可以不同。游戏开始由两个人轮流取石子。游戏规定,每次有两种不同的取法,一是可以在任意的一堆中取走任意多的石子;二是可以在两堆中同时取走相同数量的石子。最后把石子全部取完者为胜者。现在给出初始的两堆石子的数目,你先取,假设双方都采取最好的策略,问最后你是胜者还是败者。
分析
对于博弈,常常使用的一种就是从必败态来思考,这样的好处就在于必败态有时比必胜态多很多。
从题解来看
必败态
\((a_i,b_i)\)
\((1,2)\)
\((3,5)\)
\((4,7)\)
\((6,10)\)
\((8,13)\)
然后一步,还是看题解。
发现
对于第 \(k\) 组必败态
令 \(\phi = \frac{\sqrt{5}+1}{2}\)
则有 \(\begin{cases}a_i=\phi*k\\b_i=a_i+k\end{cases}\)
那么这个题就好做了
假如说输入了 \(n \quad m (m\leq n)\)
如果这个是必败态的话那么 \(k = n-m\)
带入上面的公式就 ok 了。
#include <bits/stdc++.h>
#define debug puts("I ak IOI several times");
#define pb push_back
using namespace std;
template <typename T>inline void read(T& t){
t=0; register char ch=getchar(); register int fflag=1;
while(!('0'<=ch&&ch<='9')){if(ch=='-') fflag=-1;ch=getchar();}
while(('0'<=ch&&ch<='9')){t=((t<<1)+(t<<3))+ch-'0'; ch=getchar();} t*=fflag;
}
template <typename T,typename... Args> inline void read(T& t, Args&... args){
read(t);read(args...);
}
template <typename T>inline void write(T x){
if(x<0) putchar('-'),x=~(x-1); int s[40],top=0;
while(x) s[++top]=x%10,x/=10; if(!top) s[++top]=0;
while(top) putchar(s[top--]+'0');
}
int n,m;
const double phi=(1.000+sqrt(5.000))/2.000;
int main(){
read(n,m); if(n<m) swap(n,m); int k=n-m;
if(m==(int)(phi*(double)k)) cout<<"0"<<endl;
else cout<<"1"<<endl;
return 0;
}
//Welcome back,Chtholly.