D. Ehab and the Expected XOR Problem(构造 + 异或和)

该编程问题要求构造一个数组,使得其任何子段的位数XOR值既不等于0也不等于给定值x,同时子段长度应尽可能大。解决方案通过从小到大枚举数组元素并避免出现x的异或值来实现。输出为满足条件的最大长度子段及对应的数组元素。
摘要由CSDN通过智能技术生成

Problem - D - Codeforces

 

给出两个整数nn和xx,构造一个满足以下条件的数组:

对于数组中的任何元素aiai,1≤ai<2n1≤ai<2n;
没有非空的子段,其位数XOR值等于00或xx、
它的长度ll应该是最大的。
一个序列bb是一个序列aa的子段,如果bb可以通过从aa中删除几个(可能是零或全部)元素开始和几个(可能是零或全部)元素结束得到。

输入

唯一一行包含两个整数nn和xx(1≤n≤181≤n≤18,1≤x<2181≤x<218)。

输出

第一行应该包含数组ll的长度。

如果ll是正数,第二行应包含ll个空间分隔的整数a1a1,a2a2,......,alal(1≤ai<2n1≤ai<2n)--数组aa的元素。

如果有多个解决方案,打印其中任何一个。

例子

输入

拷贝

3 5
输出

复制

3
6 1 3
输入

复制

2 4
输出

复制

3
1 3 1
输入

复制

1 1
输出

拷贝

0
注意

在第一个例子中,子段的位数XOR是{6,7,4,1,2,3}{6,7,4,1,2,3}。

题解:

1.任何子段异或和不为0

2.任何子段异或和不为x

我们可以从小到大枚举i,看i^x是否出现过,出现过则跳过,否则记录下来,

f[0] = 1,因为数组中不能出现x,f[i] = 1

这样的用处是,使得我们记录数组中任意两个数得异或和,不会为x

但是依旧好像没什么用

但是其实我们直接输出,a[i]^a[i-1]就是答案

为啥?

打个比方,数组中存的是,1,2,3,4,5

输出是

1^0

2^1

3^2

4^3

5^4

这样就能比较明显得看出来,任意子段得异或和,答案都相当于,我们记录数组中的两个数得异或和,而我们保证了记录数组中任意两个数得异或和,不会为x,所以成立

#include <cstdio>
#include <cstring>
#include <algorithm>
#include<iostream>
#include<vector>
#include<set>
#include<map>
#include<cmath>
#include<queue>
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
//#define int long long
int a[1000050];
void solve()
{
	int n,x;
	cin >> n >> x;
	map<int,int> f;
	f[0] = 1;
	int cnt = 0;
	for(int i = 1;i < 1 << n;i++)
	{
		if(f[i^x])
		continue;
		a[++cnt] = i;
		f[i] = 1;
	}
	cout << cnt <<"\n";
	for(int i = 1;i <= cnt;i++)
	{
		cout << (a[i] ^ a[i - 1]) <<" ";
	}
}
//111
//110
//100
//011

signed main()
{
//	ios::sync_with_stdio(0);
//	cin.tie(0);cout.tie(0);
	int t = 1;
//	cin >> t;
	while(t--)
	{
		solve(); 
	}
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值