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,n,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,2,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,T,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;
}
总结:博弈能打表的话 尽量先打表 对前几项找规律.
.