23-取石子(一)
#include
#include
#include
#include
using namespace std;
int t,n,m;
int main()
{
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&m);
if(n%(m+1))printf("Win\n");
else printf("Lose\n");
}
return 0;
}
135-取石子(二)
#include
#include
#include
#include
using namespace std;
int main()
{
int t,n;
scanf("%d",&t);
while(t--){
scanf("%d",&n);
int a,b,tag=0;
for(int i=1;i<=n;i++){
scanf("%d%d",&a,&b);
tag^=a%(b+1);
}
if(tag)printf("Win\n");
else printf("Lose\n");
}
return 0;
}
137-取石子(三)
161-取石子(四)
#include
#include
#include
#include
#include
using namespace std;
int a,b;
double g=(1+sqrt(5))/2;
int main()
{
while(~scanf("%d%d",&a,&b)){
if(a>b)swap(a,b);
int t=(b-a)*g;
//用b-a与a/g判断相等的方法是错误的!
if(a!=t)printf("1\n");
else printf("0\n");
}
return 0;
}
358-取石子(五)
刚开始不知道是斐波那契博弈,就dfs打表打了一下,然后看错题了并且打出的是必胜点,改了改,打出了2,3,5,8,13,21,34这几个数,可以看出规律,n为斐波那契数时必败。
// 打表打出所有必败点
#include
#include
#include
#include
using namespace std;
bool dfs(int x,int k){
if(x==0)return false;
for(int i=1;i<=k;i++){
if(i>x)break;
if(!dfs(x-i,i*2))return true;
}
return false;
}
int main()
{
for(int i=2;i<=100;i++){
//第一次取枚举1~i-1
bool f=false;
for(int j=1;j
// n很大,要定义为unsigned long long型
#include
#include
#include
#include
using namespace std;
typedef unsigned long long LL;
LL n;
LL f[110];
int main()
{
f[0]=0;f[1]=1;
for(int i=2;i<94;i++)
f[i]=f[i-1]+f[i-2];
while(cin>>n){ // 用cin/%llu读入n
if(binary_search(f,f+94,n))printf("No\n");
else printf("Yes\n");
}
return 0;
}
585-取石子(六)
#include
#include
#include
#include
#include
using namespace std;
const int Max_n=1e6+10;
int t,n;
int main()
{
scanf("%d",&t);
while(t--){
scanf("%d",&n);
int c,tag=0;
for(int i=1;i<=n;i++){
scanf("%d",&c);
tag^=c;
}
printf("%s\n",tag?"PIAOYI":"HRDV");
}
return 0;
}
833-取石子(七)
画画找规律,找到了一开始自己也不信,但是想一想,它是难度为1的博弈题!
#include
#include
#include
using namespace std;
int n;
int main()
{
while(~scanf("%d",&n)){
if(n==1||n==2)printf("Hrdv\n");
else printf("Yougth\n");
}
return 0;
}
886-取石子(八)
Wythoff博弈,不算很难,但是注意点很多,WA了好多次,慢慢来~
#include
#include
#include
#include
#include
using namespace std;
const int Max_n=1e6+10;
int a,b;
int m[Max_n],n[Max_n];
double g=(1+sqrt(5))/2;
int main()
{
int f;
for(int i=0;i<=Max_n;i++){ //预处理出所有的奇异局势
m[i]=i*g;
n[i]=m[i]+i;
if(m[i]>Max_n){
f=i;break;
}
}
while(~scanf("%d%d",&a,&b)&&a+b){
if(a>b)swap(a,b);
int t=(b-a)*g,k;
//用b-a与a/g判断相等的方法是错误的!
if(a!=t)printf("1\n");
else {printf("0\n");continue;}
if(a>t) //两堆中同时取
printf("%d %d\n",t,t+b-a);
if(a==b){ //一堆中取
k=lower_bound(n,n+f,a)-n;
if(n[k]==a)printf("%d %d\n",m[k],a);
}
else {
//大堆中取
k=lower_bound(n,n+f,a)-n;
if(n[k]==a)printf("%d %d\n",m[k],a);
k=lower_bound(m,m+f,a)-m;
if(m[k]==a&&b>n[k])printf("%d %d\n",a,n[k]);
//小堆中取
k=lower_bound(n,n+f,b)-n;
if(n[k]==b&&a>m[k])printf("%d %d\n",m[k],b);
}
}
return 0;
}
测试样例:
5 7
>1
>3 5 //两堆中取
>3 5 //大堆中取4个石子
>4 7 //小堆中取1个石子
5 6
>1
>1 2
>3 5
3 10
>1
>3 5
10 10
>1
>0 0
>6 10
888-取石子(九)
反尼姆博弈,真的不会,首先它不是ICG游戏,不可以用SG求解,然后自己P/N分析只能分析到两堆的情况,三堆以上就很复杂了。推荐一下知乎大佬王希的关于反尼姆博奕的回答。
#include
#include
#include
#include
using namespace std;
int t,n;
int main()
{
scanf("%d",&t);
while(t--){
scanf("%d",&n);
int tag=0,ans=0,t;
for(int i=1;i<=n;i++){
scanf("%d",&t);
if(t>1)ans++; //记录富裕堆的个数
tag^=t;
}
if(!tag&&!ans||tag&&ans)printf("Yougth\n");
else printf("Hrdv\n");
}
return 0;
}
913-取石子(十)
SG打表的运用,根据打表找规律,第2和第4种取法没有规律可寻!
#include
#include
#include
#include
#include
using namespace std;
const int Max_n=1e3+10;
int n;
int sg2[Max_n],sg4[Max_n],f[Max_n];
bool s[Max_n];
void get_SG(){ //第2和4种取法无规律,SG打表
f[0]=1;f[1]=2;
int N;
for(int i=2;i<=1010;i++){
f[i]=f[i-1]+f[i-2];
if(f[i]>1010){N=i;break;}
}
sg2[0]=0;
for(int i=1;i<=1010;i++){
memset(s,0,sizeof(s));
for(int j=0;i>=f[j]&&j