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