牛客练习赛59 D—取石子游戏

链接:https://ac.nowcoder.com/acm/contest/4743/D
来源:牛客网
 

题目描述

 小灰灰和小乔在玩取石子游戏,一堆石子有n{n}n个石子,小灰灰和小乔轮流操作,小灰灰先手,每次操作的人可以进行以下操作:

       假设当前石子数量为k{k}k,如果k>=2{k>=2}k>=2,那么将石子分为f(k){f(k)}f(k)和k−f(k){k-f(k)}k−f(k)两堆,然后选择其中任意一堆石子取走。否则当前操作的人输。

       其中f(k)=x{f(k)=x}f(k)=x,x{x}x为满足满足x∗2<=k{x*2<=k}x∗2<=k的最大整数。

       小灰灰和小乔都非常聪明,所以都会采用最优的策略,你知道最后小灰灰和小乔谁能赢得游戏吗?

输入描述:

 

输入共包含t{t}t组数据

第一行一个整数t{t}t,表示测试用例的组数

接下来t{t}t行每行一个整数n{n}n。

输出描述:

 

对于每组案例,如果小灰灰赢,输出“XiaoHuiHui”{“XiaoHuiHui”}“XiaoHuiHui”,否则输出“XiaoQiao”{“XiaoQiao”}“XiaoQiao”,不带双引号。

示例1

扫描二维码关注公众号,回复: 9823782 查看本文章

输入

10
1
2
3
4
5
6
7
8
9
10

输出

XiaoQiao
XiaoHuiHui
XiaoHuiHui
XiaoQiao
XiaoQiao
XiaoQiao
XiaoHuiHui
XiaoHuiHui
XiaoHuiHui
XiaoHuiHui

备注:

 

1<=t<=100000{1<=t<=100000}1<=t<=100000

1<=n<=1e18{1<=n<=1e18}1<=n<=1e18

思路:
官方题解打表找规律之后二分;规律是 1 2 3 7 13...也就是说先手赢和后手赢是一段一段出现的,并且每一段的长度在不断增加,先手的长度是之前后手长度的二倍+1,后手的长度是之前先手长度的二倍-1;然后记录每一段长度的左右临界点,对于n,去二分他在哪个范围内即可;

贪心角度:

其实从贪心的角度来看,每次取的石头的个数是奇偶交替的(并且先是奇数),所以从1开始模拟,乘2+1 和 乘2  交替进行,当进行到大于n时结束;判断进行了多少次,如果进行的次数为偶数,那么先手先碰到只剩1个石子的情况;那么先手必败;反之亦然;

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int main()
{
	int t;
	cin >>t;
	while(t--)
	{
		ll n,cnt=1,res=1;
		cin >>n;
		while(cnt<n)
		{
			if(!res) cnt*=2;
			else cnt=cnt*2+1;
			res^=1;
		}
		if(res) cout <<"XiaoQiao"<<endl;
		else cout <<"XiaoHuiHui"<<endl;
	}
}
发布了217 篇原创文章 · 获赞 49 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/weixin_43872728/article/details/104851906