CF1722G Even-Odd XOR#817(div.4)

题目链接

https://codeforces.com/problemset/problem/1722/G

题意简述

题意很简单啦

样例

点击查看样例

image

分析

首先说几个异或运算的性质.异或运算满足交换律,结合律
并且,
a 异或 b0 a=b

要使奇数项异或等于偶数项异或,当且仅当数组中所有元素异或为 0

下面我们要构造一个这样的数组

我们显然有 a 异或 a0
只需要让前面一些元素任取(不妨从 1n当中挨个取),设他们的异或值为 c
然后最后两个元素分别取 c 异或 aa ( a 是固定的一个较大的数 ,后面再说说 a 的取值限制条件)

他们异或起来就是 c 异或 (c 异或 a) 异或 a 显然为 0

注意特判 c0 的情况,若 c0 ,那么 c 异或 a 就是 a ,最后两个元素相等了.
此时只需要改动前面一个数(选一个没用过的数),那么 c 就不为 0 了,然后重新再取.

a 的取值的限制条件

本来想的是 an ,但是这样的话,和原来的数很接近,导致 c 异或 a 的结果可能在前面已经出现过,参见下例
Sample Input

1
6

Sample Output

1 2 3 4 2 6

所以把 a 取的大一点.可以直接取 a 等于 2147483647
或者观察一下题目: n 最大是 2e5 ,二进制最高位的1是从右往左第18位
那么只要让 a1<<19就能保证 a 异或 c 的值大于 n2 (前n-2个数的取值) 了
01000000000000000000 (1<<19) (左起第二位的数不受影响)
00110000110101000000 2 e5(只能在左起第三位开始变化)

代码

点击查看代码
#include<bits/stdc++.h>

using namespace std;
typedef long long LL;
int res[200010];
int main()
{
	//freopen("uva.txt","r",stdin);
	int n;
	scanf("%d",&n);
	int ans=0;
	for(int i=1;i<=n-2;i++)
	{
		ans=ans^i;
		res[i]=i;
		//printf("%d ",i);
	}
	int a=2147483647;
	if(ans==0)
	{
		ans^=res[1];
		res[1]=2147483646;
		ans^=res[1];
	}
	for(int i=1;i<=n-2;i++)
	{
		printf("%d ",res[i]);
	}
	printf("%d %d",ans^a,a);
	return 0;
}


如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮,您的“推荐”将是我最大的写作动力!欢迎各位转载,但是未经作者本人同意,转载文章之后必须在文章页面明显位置给出作者和原文连接,否则保留追究法律责任的权利。
posted @   Rainy_L  阅读(37)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端
点击右上角即可分享
微信分享提示