ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

210. 异或运算

2022-07-29 13:31:36  阅读:170  来源: 互联网

标签:le 运算 210 int 整数 异或 线性 define


题目链接

210. 异或运算

给定你由 \(N\) 个整数构成的整数序列,你可以从中选取一些(至少一个)进行异或(\(\operatorname{xor}\))运算,从而得到很多不同的结果。

请问,所有能得到的不同的结果中第 \(k\) 小的结果是多少。

输入格式

第一行包含整数 \(T\),表示共有 \(T\) 组测试数据。

对于每组测试数据,第一行包含整数 \(N\)。

第二行包含 \(N\) 个整数(均在 \(1\) 至 \(10^{18}\) 之间),表示完整的整数序列。

第三行包含整数 \(Q\),表示询问的次数。

第四行包含 \(Q\) 个整数 \(k_1,k_2,…,k_Q\),表示 \(Q\) 个询问对应的 \(k\)。

输出格式

对于每组测试数据,第一行输出 Case #C:,其中 \(C\) 为顺序编号(从 \(1\) 开始)。

接下来 \(Q\) 行描述 \(Q\) 次询问的结果,每行输出一个整数,表示第 \(i\) 次询问中第 \(k_i\) 小的结果。

如果能得到的不同结果的总数少于 \(k_i\),则输出 \(-1\)。

数据范围

\(1 \le N,Q \le 10000\),
\(1 \le k\_i \le 10^{18}\)

输入样例:

2
2
1 2
4
1 2 3 4
3
1 2 3
5
1 2 3 4 5

输出样例:

Case #1:
1
2
3
-1
Case #2:
0
1
2
3
-1

注意:只选取一个数字进行运算,则结果为该数字本身。

解题思路

线性基

由于线性基表示的空间和原向量组表示的空间等价,所以可以先求出线性基,用线性基来表示第 \(k\) 小数,由于线性基中每一个最高位的元素仅有一个,可以将每一个线性基元素当作一位,求第 \(k\) 小数即将 \(k\) 的二进制数表示出来相应乘以线性基元素,另外由于线性基不能表示 \(0\),所以需要判断原向量组是否线性相关或无关,如果向量组的秩 \(k<n\),则线性相关,即可以表示出 \(0\),否则不能

  • 时间复杂度:\(O(63n)\)

代码

// Problem: 异或运算
// Contest: AcWing
// URL: https://www.acwing.com/problem/content/description/212/
// Memory Limit: 32 MB
// Time Limit: 1000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

// %%%Skyqwq
#include <bits/stdc++.h>
 
//#define int long long
#define help {cin.tie(NULL); cout.tie(NULL);}
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;
 
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
 
template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; }
template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; }
 
template <typename T> void inline read(T &x) {
    int f = 1; x = 0; char s = getchar();
    while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
    while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
    x *= f;
}

const int N=10005;
int t,n,k,q;
LL x,a[N];
int main()
{
    scanf("%d",&t);
    for(int T=1;T<=t;T++)
    {
    	printf("Case #%d:\n",T);
    	scanf("%d",&n);
    	for(int i=0;i<n;i++)scanf("%lld",&a[i]);
    	k=0;
    	for(int i=62;i>=0;i--)
    	{
    		for(int j=k;j<n;j++)
    			if(a[j]>>i&1)
    			{
    				swap(a[k],a[j]);
    				break;
    			}
    		if(!(a[k]>>i&1))continue;
    		for(int j=0;j<n;j++)
    			if(j!=k&&(a[j]>>i&1))a[j]^=a[k];
    		k++;
    		if(k==n)break;
    	}
    	reverse(a,a+k);
    	bool f=k<n;
    	scanf("%d",&q);
    	while(q--)
    	{
    		scanf("%lld",&x);
    		x-=f;
    		if(x>=(1ll<<k))
    		{
    			puts("-1");
    			continue;
    		}
    		LL res=0;
			for(int i=0;i<k;i++)
				if(x>>i&1)res^=a[i];
    		printf("%lld\n",res);
    	}
    }
    return 0;
}

标签:le,运算,210,int,整数,异或,线性,define
来源: https://www.cnblogs.com/zyyun/p/16531957.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有