(蓝桥真题)异或数列(博弈)

文章分析了在异或数列中确定最大异或值的问题,通过位运算考虑,当某位上的1数量为奇数时,可以决定胜负。若1的数量为1,则先手赢;若1的数量大于1,且为0的数是偶数,先手赢;否则,先手输。给出了C++代码实现。

题目链接:P8743 [蓝桥杯 2021 省 A] 异或数列 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

样例输入:

4
1 1
1 0
2 2 1
7 992438 1006399 781139 985280 4729 872779 563580

样例输出:

1
0
1
1

分析:容易想到对于异或最大值的问题肯定是按位来进行考虑,优先考虑权值比较高的位,假如我们当前考虑第pos位(那么就是前pos位并没有分出胜负),不妨假设有x个数该位为1,那么就有n-x个数该位为0.

假如x是偶数,那么显然在该位上是分不出胜负的,因为如果要是Alice有t个数该位为1,那么无论怎样分,t和x-t奇偶性都相同,那么异或起来值是相同的

假如x是奇数,那么显然在该位一定可以分出胜负,因为无论怎样分,最后都只有一个人可以在该位为1.

在这种情况下还需要分情况讨论:

如果x=1,那么显然Alice首次操作会直接选该位为1的数,那么Alice直接获胜

如果x!=1,那么也就是说x是一个大于1的奇数,这个时候如果该位为0的个数n-x是偶数那么先手获胜,否则先手必败。先来说一下先手必胜的操作方法,先手先取一个该位为1的数,接下来该位为1的数和为0的数剩余的个数都是偶数个,那么先手只需要跟随后手的操作即可,也就是说假如后手选一个该位为1的数操作自己,那么先手就选一个该位为1的数操作后手,这样后手在该位始终为0,同理可分析其他类似操作,这样先手必胜。那么下面说一下如果n-x是奇数时先手必败的原因,假如先手先选取一个该位为1的数操作自己,那么后手就选择一个该位为0的数操作自己,这个时候该位为1的数和为0的数都变为了偶数个,接下来如果先手选择该位为0的数操作,那么后手也选择该位为0的数操作,这样可以维持该位为0的数的个数一直是偶数,如果先手选择该位为1的数操作自己,那么先手该位就会为0,那么这个时候后手选取该位为1的数操作自己,那么后手在该位上就会为1,在此之后无论先手怎么操作,后手总能使得后手该位为1,先手该位为0,这个是很好分析的。如果先手选择该位为1的数操作后手,那么后手该位就变为了1,那么同理后手可选择该位为1的数操作先手,这个时候也能到达后手该位为1,先手该位为0的状态,接下来就跟上面一样,后手总能使得后手该位为1,先手该位为0,那么后手必胜!如果先手先选取一个该位为0的数操作自己,那么相对于后手的局面就变为先手操作,而且该位为1的个数为奇数,且为0的个数为偶数,所以是必胜局面。综上所述,对于该局面,后手必胜!

细节见代码:

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<vector>
#include<queue>
using namespace std;
const int N=2e5+10;
int a[N];
int num[31];
int Log2[1<<22];
int lowbit(int x)
{
	return x&-x;
}
int main()
{
	int T,n;
	for(int i=0;i<=20;i++)
		Log2[1<<i]=i;
	cin>>T;
	while(T--)
	{
		scanf("%d",&n);
		for(int i=20;i>=0;i--)
			num[i]=0;
		for(int i=1;i<=n;i++)
		{
			scanf("%d",&a[i]);
			while(a[i])
			{
				num[Log2[lowbit(a[i])]]++;
				a[i]-=lowbit(a[i]);
			}
		}
		bool flag=false;
		for(int i=20;i>=0;i--)
			if(num[i]&1)
			{
				flag=true;
				if(num[i]==1)
					puts("1");
				else if(n&1)//该位为1的个数大于1且为0的个数是偶数 
					puts("1");
				else
					puts("-1");//该位为1的个数大于1且为0的个数是奇数
				break;
			}
		if(!flag) puts("0");
	}
	return 0;
} 

<think>好的,我现在需要处理用户关于蓝桥杯竞赛中浮点数处理的真题或解法的请求。首先,我要确认用户的具体需求:他们可能在寻找蓝桥杯历年真题中涉及浮点数处理的题目,以及相应的解决方法。接下来,我需要回忆蓝桥杯的常见题型,尤其是Python组的题目,因为用户提供的引用中提到了Python组的情况。 根据引用[1]和[2],蓝桥杯青少组和省赛的题目难度适中,但需要扎实的基础。浮点数处理通常涉及精度控制、四舍五入、避免累积误差等问题。常见的考点可能包括格式化输出、小数运算技巧、比较浮点数时的注意事项等。 我需要先整理几个典型的蓝桥杯浮点数处理题目。例如,可能存在要求计算特定数学问题并保留小数位数的情况,或者处理浮点数的输入输出格式。此外,可能还有涉及避免浮点数计算误差的题目,比如使用整数运算代替浮点数运算来保持精度。 接下来,针对每个题目类型,我需要给出具体的解决方法和代码示例。例如,使用Python的round函数进行四舍五入,或者使用decimal模块处理高精度计算。同时,要注意蓝桥杯竞赛中可能对输出格式的严格要求,比如必须保留两位小数,这时候需要正确的格式化字符串方法。 另外,用户提供的引用中提到,即便是最后一个大题,实现起来也不难,关键在于理解题意并转换为代码。因此,在解答时,可能需要强调问题分析和将问题分解为编程步骤的能力。 最后,生成相关问题时要围绕浮点数处理的不同方面,比如精度控制、运算优化、常见错误等,帮助用户全面了解该考点。</think>### 蓝桥杯浮点数处理真题及方法 #### 典型真题示例 1. **保留小数位数问题** **题目**:计算圆的面积,保留7位小数(输入半径$r$,输出面积$S$)[^1]。 **解法**:使用Python的字符串格式化或`round`函数。 ```python import math r = float(input()) S = math.pi * r ** 2 print("{:.7f}".format(S)) # 直接格式化输出 # 或 print(round(S, 7)) # 注意:round可能末尾补零不足需处理 ``` 2. **浮点数精度陷阱** **题目**:判断两个浮点数$a$和$b$是否相等,若$|a - b| < 1e-9$则认为相等[^2]。 **解法**:避免直接`a == b`,改用误差范围判断。 ```python a = float(input()) b = float(input()) if abs(a - b) < 1e-9: print("相等") else: print("不等") ``` 3. **浮点数运算转整数优化** **题目**:计算浮点数数组平均值,保留两位小数(例如:输入`[1.2, 3.4, 5.6]`,输出`3.40`)。 **解法**:利用整数运算避免累积误差。 ```python nums = list(map(float, input().split())) total = sum(int(x * 100) for x in nums) # 转为分计算 avg = total / len(nums) print("{:.2f}".format(avg / 100)) ``` #### 核心技巧总结 1. **输出格式化** - 使用`format`函数:`"{:.Nf}".format(x)`保留$N$位小数。 - 注意补零:如要求必须显示两位小数,即使末尾是零(例如`3.4`需输出`3.40`)。 2. **高精度计算** - 需要精确小数时,用`decimal`模块: ```python from decimal import Decimal, getcontext getcontext().prec = 20 # 设置精度位数 result = Decimal('0.1') + Decimal('0.2') # 精确计算0.3 ``` 3. **避免浮点误差** - 比较时用误差阈值(如`1e-9`)。 - 涉及货币、分数时,优先转为整数计算(如以分为单位)。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值