浅谈博弈论

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.
posted @ 2021-12-17 14:48  Mercury_City  阅读(105)  评论(0编辑  收藏  举报