210. 异或运算

题目链接

210. 异或运算

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

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

输入格式

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

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

第二行包含 N 个整数(均在 11018 之间),表示完整的整数序列。

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

第四行包含 Q 个整数 k1,k2,,kQ,表示 Q 个询问对应的 k

输出格式

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

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

如果能得到的不同结果的总数少于 ki,则输出 1

数据范围

1N,Q10000,
1k_i1018

输入样例:

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; }

__EOF__

本文作者acwing_zyy
本文链接https://www.cnblogs.com/zyyun/p/16531957.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   zyy2001  阅读(59)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示

喜欢请打赏

扫描二维码打赏

支付宝打赏