Mahmoud and Ehab and the xor

题目

传送门 to VJ

题意概要
求一个非负整数集合 S S S ,其大小为 n n n ,其元素的异或和为 x x x 。集合内的数字不得超过一百万。

数据范围与约定
n , x ≤ 1 0 5 n,x\le 10^5 n,x105 ,输出任意一组解即可。无解输出 N O \tt{NO} NO

思路

数据范围很大, d p \tt{dp} dp 等都不那么可做。考虑构造一组解。

如果 n n n 是奇数,我们用这样一招:

  • 初始化:先随便选 n n n 个不同的非负整数。
  • 进行微调:如果将每个数字都异或上 p p p ,那么总异或和就会异或 p p p ,而且各个数字仍然互不相同。取 p = 2 m p=2^m p=2m 即可。

如果 n n n 是偶数,我们试着直接使用一个 x x x ,所以用 n − 1 n-1 n1 构造异或和为零的情况,然后讨论一下。

  • 如果这 n − 1 n-1 n1 个数中不包含 x x x ,直接将 x x x 加入即可。
  • 如果包含 x x x ,将 x x x 与另外一个数字一起异或一个足够大的数字(比如 2 18 2^{18} 218 )。

异或足够大的数字之后,该数字将不会与已有的数字相同。

代码

#include <cstdio>
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstdlib>
using namespace std;
inline int readint(){
	int a = 0; char c = getchar(), f = 1;
	for(; c<'0' or c>'9'; c=getchar())
		if(c == '-') f = -f;
	for(; '0'<=c and c<='9'; c=getchar())
		a = (a<<3)+(a<<1)+(c^48);
	return a*f;
}
inline void writeint(long long x){
	if(x > 9) writeint(x/10);
	putchar((x%10)^48);
}
# define MB template < class T >
MB void getMax(T &a,const T &b){ if(a < b) a = b; }
MB void getMin(T &a,const T &b){ if(b < a) a = b; }

const int MaxN = 1000005;
int n, a[MaxN];
void build(int want){
	for(int i=1; i<=n; ++i)
		want ^= (a[i] = i);
	for(int i=1; i<=n; ++i)
		a[i] ^= want;
} // 构造一组解。仔细思考即可明白。

int main(){
	n = readint(); int want = readint();
	if(n == 2 and want == 0){
		puts("NO"); return 0;
	} // 唯一的无解情况
	if(n%2 == 1){
		build(want);
		puts("YES");
		for(int i=1; i<=n; ++i)
			printf("%d ",a[i]);
		return 0;
	}
	-- n, build(0);
	for(int i=1; i<=n; ++i)
		if(a[i] == want){
			a[i] ^= (1<<18);
			if(i != 1)
				a[1] ^= (1<<18);
			else a[2] ^= (1<<18);
		}
	puts("YES");
	for(int i=1; i<=n; ++i)
		printf("%d ",a[i]);
	printf("%d\n",want);
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值