bash博弈:
一堆石子,有n个石子,每一次最多取k个,问你谁先获胜。 直接判断 n % (k +1 )是否为0,如果是0的话就是奇异局(只要对面不是傻逼的话就一定会输的局,否则就是对面赢。
题目链接:https://cn.vjudge.net/contest/257365#problem/A
AC代码:
#include<iostream>
#include<string>
#include<iomanip>
#include<cstring>
#include<cmath>
#include<map>
#include<algorithm>
#include<stdio.h>
using namespace std;
# define maxn 1000000+10
# define inf 0x3f3f3f3f
# define ll long long
int main(){
int T;
scanf("%d",&T);
while(T--){
int n,m;
scanf("%d%d",&n,&m);
if(m>=n)printf("A\n");
else {
if(n%(m+1))printf("A\n");
else printf("B\n");
}
}
return 0;
}
尼姆博弈:
有n堆石子,每一次可以拿任意多个,问你谁拿最后一个。
解题方法:直接将每一堆的石子异或,如果最终结果是0的话就代表是奇异局,否则就是非奇异局。
题目链接:https://cn.vjudge.net/contest/257365#problem/C
AC代码:
#include<iostream>
#include<string>
#include<iomanip>
#include<cstring>
#include<cmath>
#include<map>
#include<algorithm>
#include<stdio.h>
using namespace std;
# define maxn 1000000+10
# define inf 0x3f3f3f3f
# define ll long long
int vis[maxn];
int ans[maxn];
int main()
{
int n;
scanf("%d",&n);
int temp;
scanf("%d",&temp);
for(int i=2;i<=n;i++){
int t;
scanf("%d",&t);
temp=temp^t;
}
if(temp==0)printf("B\n");
else printf("A\n");
return 0;
}
威佐夫博弈:
两堆石子,每一个可以从一堆里面拿任意个或者从两堆里面拿相同的个数,问你最后谁拿完。
判断方法:如果满足 最大值和最小值的差值乘以黄金分割率等于最小值,那么当前的局面就是奇异局,否则就是非奇异局。
题目链接:https://cn.vjudge.net/contest/257365#problem/D
AC代码:
#include<iostream>
#include<string>
#include<iomanip>
#include<cstring>
#include<cmath>
#include<map>
#include<algorithm>
#include<stdio.h>
using namespace std;
# define maxn 1000000+10
# define inf 0x3f3f3f3f
# define ll long long
# define gold (sqrt(5.0)+1.0)/2.0
ll maxx(ll t1,ll t2){
if(t1>t2)return t1;
return t2;
}
ll minn(ll t1,ll t2){
if(t1>t2)return t2;
return t1;
}
int main()
{
ll T; ll n,m;
while(~scanf("%lld%lld",&n,&m))
{
ll a,b;
a=maxx(n,m);
b=minn(n,m);
int t=(a-b)*gold;
// cout<<a<<" "<<b<<" "<<t<<" "<<gold<<endl;
if(b==t)printf("0\n");
else printf("1\n");
}
return 0;
}
分割线/-----------------------------------------------------------------------------------------------------------------------------------/
上面这些只是基本的模型,如果是稍微修改题意就可能套不上模板了,比如说下面这个题。
https://cn.vjudge.net/contest/257365#problem/B
这个时候就需要用到sg函数了,先介绍mex函数,这个函数的作用是先找到第一个在当前的区间内非负的值。
比如说,mex[1 3 5 7] = 0 . mex[ 1 ] = 0 ,mex[2 5 7 8]= 0.mex[ 0] =1;
然后再开始介绍sg,就拿例题作解释。
当只有一颗石子的时候,它的后继状态只有0 (1-1=0) ,sg[1]=mex(sg[0])=1.
当只有两颗石子的时候,他的后继状态变成了1(2-1=1),sg[2]=mex(sg[1])=0,那么这个时候就是奇异局了,也就是说只要对面不是傻逼的话,自己就一定会输。
当只有三颗石子的时候,他的后继状态变成了2(3-1=2),0(3-3=0),所以说,sg[3]=mex(sg[2],sg[0])=2.
以此类推,就可以推出当石子数为n的时候是不是博弈局了。一般的话如果数据量不大的话,可以直接暴力,如果数据量大的话,就可以通过sg打表找规律了。