首页 > 其他分享 >HDU-3949 XOR 题解报告

HDU-3949 XOR 题解报告

时间:2023-01-09 21:58:52浏览次数:58  
标签:3949 HDU int 题解 -- 异或 base 线性 向量

题目地址

题意:

从一个序列中取任意个元素进行异或,求能异或出的所有数字中的第 k 小。

分析:

性质:一个线性基异或上另一个不同的线性基,并作为自己的新值,这并不改变整个线性基的性质(线性基只有元素数量是固定的)。

从大到小枚举每一个线性基d[i],从它的第二高位往低位扫,如果扫到d[i]在第j位是1,那么就异或上d[j](d[j]最高位是1),这样就消去d[i]在第j位上的1。当然d[ j ]这个向量可能不存在。那么原本该位的1不变。那么处理完一个线性基之后,应该大致是长这个样子的(x表示0或1):

   1xxxx0xxx0x
        1xxx0x
            1x

也就是,每个线性基元素的最高位1,只会由自己贡献,这依旧满足线性基基本性质。我们把这些新元素放入新数组_base,无视旧数组中的空向量,记新数组大小为cnt。_base数组具有与二进制基数一样特点:

  1. 每个向量选或不选;
  2. 往一个集合中加入新向量,或者把集合中一个元素换做更大的向量,集合异或和会变大;
  3. 比向量X小的所有向量的异或和,仍小于X。

如果k的第 i 位为1,那么结果就异或上 _base[i],最后便得到了第 k 小。

额外补充:

给予一组元素,每个数互异且遍布了2的幂,即 \(2^0,2^1,2^2,2^3,2^4...\)。定义一个集合的大小为这个集合中的元素之和,我们想知道在上述序列中,第k小的子集的大小。很显然,这个第k小子集的大小就是 k 本身。比如k是(1001),结果便是(\(2^0+2^3\))。

如果我们去掉某些权位,比如得到 \(2^0,\_\ ,2^2,2^3,\_\ ,2^5,...\),再询问第k小。那么,对于序列的所有子集的值,在二进制表示下,位权缺失的位都为0,无视这些位后仍可视作二进制数。于是我们可以直接剔除缺失部分,以其他数代位。对于k是(1001),结果便为(\(2^0+2^5\))。

代码:

#include<bits/stdc++.h>
using namespace std;
using ll = long long;

int main()
{
	cin.tie(0)->sync_with_stdio(false);
	int T;
	cin>>T;
	for(int NO=1;NO<=T;++NO)
	{
		cout<<"Case #"<<NO<<":\n";
		ll base[65] = {0};
		int zero=0;
		int n;
		cin>>n;
		for(int i=1;i<=n;++i)
		{
			ll x;
			cin>>x;
			for(int j=63;j>=0;--j)
			{
				if(x>>j)
				{
					if(base[j])
						x^=base[j];
					else{
						base[j]=x;
						break;
					}
				}
			}
			if(x==0)
				zero=1;
		}
		vector<ll> b;
		for(int i=63;i>=0;--i)
		{
			if(!base[i])
				continue;
			for(int j=i-1;j>=0;--j)
			{
				if((base[i]>>j)&1)
				{
					base[i]^=base[j];
				}
			}
			b.push_back(base[i]);
		}
		reverse(b.begin(),b.end());
		int m = b.size();
		int q;
		cin>>q;
		while(q--)
		{
			ll k;
			cin>>k;
			if(k>=(1LL<<m)+zero)
			{
				cout<<"-1\n";
				continue;
			}
			k-=zero;
			ll ans=0;
			for(int i=0;i<64;++i)
			{
				int r=((k>>i)&1);
				if(r)
					ans^=b[i];
			}
			cout<<ans<<"\n";
		}
	}
}

标签:3949,HDU,int,题解,--,异或,base,线性,向量
From: https://www.cnblogs.com/blover/p/17038612.html

相关文章

  • 【CF802O】April Fools' Problem (hard) 题解 (线段树模拟费用流)
    线段树模拟费用流。LG传送门。SolutionPart1根据题面,显然想到此题是费用流。建图方式亦是显然:\(S\rightarrowi\),流量为\(1\),费用为\(a_i\);\(i\rightarrowT_0\)......
  • contest739E. Gosha is hunting 题解报告
    题目地址题意:现在一共有\(n\)只神奇宝贝。你有\(a\)个『宝贝球』和\(b\)个『超级球』。『宝贝球』抓到第\(i\)只神奇宝贝的概率是\(p_i\),『超级球』抓到的......
  • 牛客小白月赛65D题 牛牛取石头 题解
    原题链接第一眼看到这道题,其实很容易会联想到经典的bashgame问题这道题并没有巴什博弈那么复杂,但也算一道比较新颖的博弈论题吧还是很适合作为一道博弈论入门题的题......
  • P8932 [JRKSJ R7] Clock Paradox 题解
    在洛谷上阅读Part0题意简述原题这场月赛我唯一AC的题给出一个字符串\(S\),令\(T=S\),求使用\(S\)的子串插入\(T\),将\(T\)变形的最少的操作次数。且字符串\(S\)......
  • Educational Codeforces Round 141 (Rated for Div. 2) A-C题解
    比赛链接A、MakeitBeautiful一种构造方法:按照从大到小的顺序构造,可以发现前缀和永远大于当前值。但是需要特判存在两个最大值的情况。只需要将最小值与第二位交换位置......
  • P5999 [CEOI2016] kangaroo 题解
    分析一个妙妙的trick。首先原题可以转化成求有多少\(1\simn\)的排列\(p\)满足\(\foralli\in(1,n)\),\(p_i\)两边的数同时小于或大于\(p_i\),且\(p_1=s,p_n=t\)......
  • WC 2018 题解
    A若干套路拼起来的胖题。设这三棵树分别是\(T_1,T_2,T_3\)。沿用“CTSC2017暴力写挂”的思路,对第一棵树点分治,此时要处理的是以\(u\)为中心的一块在\(T_1\)上的连......
  • CF652F 题解
    题意传送门在一个长度为\(m\)的圆环上有\(n\)只初始位置互不相同的蚂蚁,每只蚂蚁的速度都为\(1\),初始方向为顺时针或逆时针;两只运动方向不同的蚂蚁相遇时会调转方向,......
  • Codeforces 1671 F Permutation Counting 题解
    题目链接把\(p_i>p_{i+1}\)的位置个数称为间隔数首先想到一个暴力做法。从小到大挨个添加1-n中的每个数,注意到添加数i时,只能添加到当前序列的最后11个位置中,否则逆序对数......
  • hdu:张煊的金箍棒(2)(线段树)
    ProblemDescription张煊的金箍棒升级了!升级后的金箍棒是由几根相同长度的金属棒连接而成(最开始都是铜棒,从1到N编号);张煊作为金箍棒的主人,可以对金箍棒施以任意的变换,每......