牛客——取石子游戏 (博弈)

取石子游戏
题意: 给你含有k个石子的石子堆。假设当前石子数量为k,如果k>=2,那么将石子分为f(k)和k−f(k)两堆,然后选择其中任意一堆石子取走。否则当前操作的人输。其中f(k)=x,x为满足满足x∗2<=k的最大整数。
小灰灰和小乔都非常聪明,所以都会采用最优的策略,你知道最后小灰灰和小乔谁能赢得游戏吗?

分析: 容易知道如果轮到某方时k=1,那么他输了,现在来分析胜利和失败是如何进行转化的,假设轮到小灰灰时有k个石子,我们令a=k/2,b=k-k/2。

1.a为必胜态,b为必胜态。
如果小灰灰选择a,那么就把b留给了对手(因为b为必胜态,下同),对手胜;如果小灰灰选择b,那么就把a留给了对手,对手胜。则k为必败态。

2.a为必胜态,b为必败态。
小灰灰选择只要选择a,将b留给对手,那么小灰灰就胜利了。(因为对手得到的b为必败态),则k为必胜态。

3.a为必败态,b为必胜态。
小灰灰选择只要选择b,将a留给对手,那么小灰灰就胜利了。(因为对手得到的a为必败态),则k为必胜态。

4.a为必败态,b为必败态。
那么小灰灰不管选择那个,对手都将得到的必败态,则k为必胜态。

分析完后写个程序来找规律。

打表代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2020;
bool book[N];
ll a[1010];
int main(){
	
	book[1]=false; //1为必败态
	printf("XiaoQiao\n");
	for(int i=2;i<=1000;i++){
		if(book[i/2]==false&&book[i-i/2]==false) book[i]=true;
		else if(book[i/2]==true&&book[i-i/2]==true) book[i]=false;
		else book[i]=true;
		if(book[i]) printf("XiaoHuiHui\n");
		else printf("XiaoQiao\n");
	}

    

   	
	return 0;
} 

AC代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2020;
bool book[N];
ll a[1010];
int main(){
	
	  a[1]=1;a[2]=2;
	  for(int i=3;i<=61;i++){
	  	 if(i&1) a[i]=2*a[i-1]-1;
	  	 else a[i]=2*a[i-1]+1;
	  
	  }
	  for(int i=2;i<=61;i++){
	  	a[i]=a[i-1]+a[i];
	  }
	  	
	   int t;
       scanf("%d",&t);

       while(t--){
       	ll n;
       	scanf("%lld",&n);
       	int p=lower_bound(a+1,a+62,n)-a;
       	if(p%2==0) printf("XiaoHuiHui\n");
       	else printf("XiaoQiao\n");
		
		
	   }
  	
   	
	return 0;
} 
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值