博弈论模板
一。巴什博弈
只是最简单的博弈了,只简单说一下满足条件,一堆总数为n个,每次可以取1-m个石头。 核心是n=(m+1)*r+s;也就是说用n%(m+1) 判断是否等于0即可。
例题:hdu 1846
- int main()
- {
- int n;
- cin>>n;
- while(n--)
- {
- int a,b;
- cin>>a>>b;
- int t=a%(b+1);
- if(t>=1)
- {
- cout<<"first"<<endl;
- }
- else
- {
- puts("second");
- }
- }
- }
二。斐波那契博弈。
要求是在一堆里,轮流取石头,每次取的石头要求在1-上一次对手取的石头的2倍之间 包括两个端点,核心是把这个数分解成斐波拉契数列,换句话说,判断这个n是否是斐波拉契数即可。
例题:hdu2516
- int main()
- {
- int n;
- int a[maxn];
- a[0]=2;
- a[1]=3;
- for(int i=2;i<=50;i++)
- {
- a[i]=a[i-1]+a[i-2];
- }
- while(cin>>n,n)
- {
- int flag=0;
- for(int i=0;i<=50;i++)
- {
- if(n==a[i])
- {
- puts("Second win");
- flag=1;
- break;
- }
- }
- if(!flag)
- {
- puts("First win");
- }
- }
- }
三。威佐夫博弈。
要求是两堆石头,两个人轮流从某一堆同时从两堆中取同样多的物品。最少一个,多则无限。
这个博弈的关键在于一个黄金分割数。
就要提到一种叫奇异局势。
意思是B-A(当然保证B>A) A=黄金分割数*(B-A)的话就是奇异局势。核心就在这里。
例题:poj 1067
- int main()
- {
- int a,b;
- while(cin>>a>>b)
- {
- if(a>b)
- swap(a,b);
- int c=floor((b-a)*((sqrt(5.0)+1)/2));
- if(c==a)
- {
- puts("0");
- }
- else
- {
- puts("1");
- }
- }
- }
四。尼姆博弈。要求是n堆里面,取一堆任意多的物品。每次取一个,多者不限。
核心也就是异或。
例题:hdu 1850
- int main()
- {
- int m;
- while(cin>>m,m)
- {
- int ans=0,sum=0;
- int a[maxx];
- for(int i=1;i<=m;i++)
- {
- cin>>a[i];
- ans^=a[i];
- }
- if(ans==0) puts("0");
- else
- {
- for(int i=1;i<=m;i++)
- {
- int k=ans^a[i];
- if(k<a[i])
- sum++;
- }
- cout<<sum<<endl;
- }
- }
- }
五。SG值。
例题:hdu 1847
- #include <bits/stdc++.h>
- //#include <ext/pb_ds/tree_policy.hpp>
- //#include <ext/pb_ds/assoc_container.hpp>
- //using namespace __gnu_pbds;
- using namespace std;
- #define pi acos(-1)
- #define endl '\n'
- #define me(x) memset(x,0,sizeof(x));
- #define foreach(it,a) for(__typeof((a).begin()) it=(a).begin();it!=(a).end();it++)
- typedef long long LL;
- const int INF=0x3f3f3f3f;
- const LL LINF=0x3f3f3f3f3f3f3f3fLL;
- const int dx[]={-1,0,1,0,-1,-1,1,1};
- const int dy[]={0,1,0,-1,1,-1,1,-1};
- const int maxn=1e3+5;
- const int maxx=2e5+100;
- const double EPS=1e-7;
- const int mod=1000000007;
- template<class T>inline T min(T a,T b,T c) { return min(min(a,b),c);}
- template<class T>inline T max(T a,T b,T c) { return max(max(a,b),c);}
- template<class T>inline T min(T a,T b,T c,T d) { return min(min(a,b),min(c,d));}
- template<class T>inline T max(T a,T b,T c,T d) { return max(max(a,b),max(c,d));}
- //typedef tree<pt,null_type,less< pt >,rb_tree_tag,tree_order_statistics_node_update> rbtree;
- /*lch[root] = build(L1,p-1,L2+1,L2+cnt);
- rch[root] = build(p+1,R1,L2+cnt+1,R2);中前*/
- /*lch[root] = build(L1,p-1,L2,L2+cnt-1);
- rch[root] = build(p+1,R1,L2+cnt,R2-1);中后*/
- long long gcd(long long a , long long b){if(b==0) return a;a%=b;return gcd(b,a);}
- int sg[maxx];
- int a[100];
- int mex(int x)
- {
- if(sg[x]!=-1) return sg[x];
- int vis[maxn];
- me(vis);
- for(int i=0;i<=10;i++)
- {
- int temp=x-a[i];
- if(temp<0) break;
- sg[temp]=mex(temp);
- vis[sg[temp]]=1;
- }
- for(int i=0;;i++)
- {
- if(!vis[i])
- {
- sg[x]=i;
- break;
- }
- }
- return sg[x];
- }
- int main()
- {
- int n;
- a[0]=1;
- for(int i=1;i<=10;i++)
- {
- a[i]=a[i-1]*2;
- }
- while(cin>>n)
- {
- memset(sg,-1,sizeof(sg));
- if(mex(n)) puts("Kiki");
- else
- puts("Cici");
- }
- }