51nod 40 Bash游戏 博弈,打表

前端之家收集整理的这篇文章主要介绍了51nod 40 Bash游戏 博弈,打表前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

Bash 游戏4题.

题意:有一堆石子共有N个。A B两个人轮流拿,A先拿。每次最少拿1颗,最多拿K颗,拿到最后1颗石子的人获胜。
n,k<=1e9,T<=1e4.


假如N%(k+1)!=0 先手必胜 因为每次可以把可以把余数变为0 下
因为最多取k个,下一个人无论怎么操作余数都不会为0,先手每次取完都为r==0的状态.经过若干次操作后.石子被先手取完,先手必胜.
#include <bits/stdc++.h>
using namespace std;
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	int T,n,k;
	cin>>T;
	while(T--)
	{
		cin>>n>>k;
		puts((n%(k+1))?"A":"B");
	}
	return 0;
}





题意:一堆石子共有N个。A B两个人轮流拿,A先拿。每次只能拿1,3,4颗,拿到最后1颗石子的人获胜
T<=1e4,n<=1e9 问先手是否必胜?

打个表 找下规律? 猜想必败态为:7k,7k+2.

若n%7!=0,2,那么先手总是可以将状态转到n%7==0,2. 不断操作后n==0,2显然为必败.

#include <bits/stdc++.h>
using namespace std;
const int N=2e5+5;
int f[N];
void init()
{
	//l:=7k,7k+2
	f[1]=f[3]=f[4]=1;
	for(int i=5;i<50;i++)
	{
		if(f[i-1]==0||f[i-3]==0||f[i-4]==0)
			f[i]=1;
		cout<<i<<' '<<f[i]<<endl;
	}
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	int T,k;
	//init();
	cin>>T;
	while(T--)
	{
		cin>>n;
		int r=n%7;
		puts((r==2||r==0)?"B":"A");	 
	}
	return 0;
}

//
题意:一堆石子共有N个。A B两个人轮流拿,A先拿。每次拿的数量只能是2的正整数次幂,比如(1,4,8,16....),拿到最后1颗石子的人获胜。
T<=1e3,N<=10^1000 问先手是否必胜?


整数n用二进制来表示 则每次操作都将二进制中某位1变为0.也可以将某位0,变成1 例如 101->011,10001->01101.
上面分析好像没什么用...先打表个表看看 发现必败态都为3的倍数

n为大数 判断n能否被三整除 看n每个位数数字之和是否被3整除即可

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e3+5;
int n,T,f[N];
string s;
void init()
{
	for(int i=1;i<=100;i++)
	{
		for(int j=1;j<=i;j<<=1)
		{
			if(f[i-j]==0)
				f[i]=1;
		}
		//cout<<i<<' '<<f[i]<<endl;
	}
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	init();
	cin>>T;
	while(T--)
	{
		cin>>s;
		int cnt=0;
		for(int i=0;s[i];i++)
			cnt+=s[i]-'0';
		puts((cnt%3)?"A":"B");
	}
	return 0;
}
 
 

题意:n个石子,A,B两人轮流取,每次拿的个数最少一个,并且不超过对手上一次拿的两倍.无法操作算输

A先手,(第一次不能全部取完).问是否必胜? N<=1e9.前三题几乎都是打表 继续打表 石头相同,能拿的个数不同,状态也就不同,设d[i][j] i个石头 最多取j个时的状态d[i][j]后继状态只要一个为必败态则该状态为必胜态. d[i][j]-> d[i-k][2*k] [k=1..min(i,j)]发现必败态为fib数.
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e3+5;
int n,m,d[N][N];
ll f[N];
string s;
void init()
{
	memset(d,-1,sizeof(d));
	for(int i=1;i<=60;i++)
	{
		for(int j=1;j<i;j++)
		{
			d[i][j]=0;
			for(int k=1;k<=j;k++)
			{
				if(d[i-k][2*k]==0)
					d[i][j]=1;
			}
		}
	//	cout<<i<<' '<<d[i][i-1]<<endl;
	}
	int i;
	f[1]=f[2]=1;
	for(i=3;f[i-1]<=1e9;i++)
		f[i]=f[i-1]+f[i-2];
	m=i;
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	init();
	cin>>T;
	while(T--)
	{
		cin>>n;
		bool flag=true;
		for(int i=1;i<m;i++)
			if(n==f[i])
				flag=false;
		puts(flag?"A":"B");
	}
	return 0;
}


总结:博弈能打表的话 尽量先打表 对前几项找规律.


.

猜你在找的Bash相关文章