CF1722G 题解

CF1722G 题解

题意

给定一个正整数 n,要求构造一个长度为 n 的数组,使得数组的奇数项的异或和等于偶数项的异或和。

有多组数据。

前置知识

位运算,知道 aa=0,0a=a

思路

注意到,题目要求每个数各不相同,于是想到可以让数组为 1,2,3,,n1,an。前面几个为各不相同的数,最后一个简单处理下即可。

但是!这样会重复,an 可能会和前面的数重复,所以令 x=123(n3),则让数组为 1,2,3,,n3,218,219,x218219。于是,就快乐地 AC 啦~~~

等等,没结束,你还没告诉我这为啥就不重复了捏?

因为,打开计算器,发现 218=262144,218>2×105,所以,前面的 (n1) 个数是互不相同的(因为 n2×105),而 x2×105,所以最后一个数是不等于前面的任何一个数的,而且它大于 219

等等!我还有疑问,为啥这是正确的捏?

其实也非常简单,有前置知识,任意一个实数 a,有 aa=0,0a=a,而我们知道,和最后一项同奇偶的项数的异或和为 219 所有数字小于 218 且与最后一项异奇偶的所有数的异或和;和最后一项异奇偶的项数的异或和为 219 所有数字小于 218 且与最后一项异奇偶的所有数的异或和。两者相同。

再等等!我懂了结论的正确性了,但你是咋推出来的呢?

很简单,要学会偷懒!做题肯定想要特殊处理的少,那既然 1 个不行,那就试试 3 个呗!而异或要是两个数在二进制下有一位有且只有一个为 1 的情况下,就为 1,而大于一个数的数一定与这个数不同,于是就考虑大于 2×1052 的指数幂,就出来啦~

哦,结束了,都懂了,上代码喽!

代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
long long T,n,x,num=1<<18;//大于200005的第一个二次方幂。
int main(){
	scanf("%lld",&T);
	while(T--){
		x=0;//注意初始化!
		scanf("%lld",&n);
		for(int i=1; i<=n-3; i++){
			printf("%lld ",i);
			x^=i;
		}
		printf("%lld %lld %lld\n",num,num<<1,x^num^(num<<1));
	}
	return 0;
} 
posted @   naroto2022  阅读(3)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示
花开如火,也如寂寞。