【线性基】51nod1312 最大异或和&LOJ114 k大异或和
2018-03-16 14:55
302 查看
1312 最大异或和
题目来源: TopCoder 基准时间限制:1 秒 空间限制:131072 KB 分值: 320 难度:7级算法题 有一个正整数数组S,S中有N个元素,这些元素分别是S[0],S[1],S[2]...,S[N-1]。现在你可以通过一个操作来更新数组。操作方法如下: 选择两个不同的数i、j(0<=i,j<N 且 i!=j),先计算A = S[i] xor S[j], B = S[j]。然后用A、B替换S[i],S[j],即 S[i]=A , S[j]=B。其中xor表示异或运算。 你可以进行任意多次操作,问最后生成的数组S的元素和 SUM = S[0]+S[1]+S[2]+...+S[N-1] 最大可能值是多少。输出这个最大值。 例如:S = {1,0},去A = S[1] xor S[0] = 1,B = S[0] = 1,新的S={1,1},SUM = 1+1 = 2. Input第一行一个整数N,且1<=N<=50 接下来N行每行一个整数S[i],且0<=S[i]<=1,000,000,000,000,000 (10^15)Output
一个整数,即最后集合可能的最大值SUM。Input示例
3 1 2 3Output示例
8
题解
处理出来线性基直接求得结果即可
代码
//by 减维 #include<set> #include<map> #include<ctime> #include<cmath> #include<queue> #include<bitset> #include<vector> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define ll long long #define il inline #define db double #define rg register #define mpr make_pair #define maxn 105 #define eps 1e-8 #define inf (1<<30) #define pi 3.1415926535897932384626L using namespace std; inline int read() { int ret=0;bool fla=0;char ch=getchar(); while((ch<'0'||ch>'9')&&ch!='-')ch=getchar(); if(ch=='-'){fla=1;ch=getchar();} while(ch>='0'&&ch<='9'){ret=ret*10+ch-'0';ch=getchar();} return fla?-ret:ret; } int n,cnt; ll mx,ans,a[maxn],b[maxn],p[65],bin[65]; int main() { n=read(); bin[0]=1;for(int i=1;i<=62;++i) bin[i]=bin[i-1]<<1; for(int i=1;i<=n;++i) scanf("%lld",&a[i]),b[i]=a[i]; for(int i=1;i<=n;++i) for(int j=62;j>=0;--j) if(a[i]&bin[j]) if(!p[j]){p[j]=a[i];break;} else a[i]^=p[j]; for(int i=62;i>=0;--i) for(int j=i-1;j>=0;--j) if(p[i]&bin[j]) p[i]^=p[j]; for(int i=62;i>=0;--i) if(p[i]) { if((mx^p[i])>mx) mx^=p[i]; cnt++; } ans+=mx*(n-cnt+1); cnt--; for(int i=0;cnt&&i<=62;i++) if(p[i]) ans+=(mx^p[i]),cnt--; printf("%lld",ans); return 0; }
#114. k 大异或和
题目描述
这是一道模板题。
给由 n n n 个数组成的一个可重集 S S S,每次给定一个数 k k k,求一个集合 T⊆S T \subseteq S T⊆S,使得集合 T T T 在 S S S 的所有非空子集的不同的异或和中,其异或和 T1xorT2xor…xorT|T| 是第 k k k 小的。
输入格式
第一行一个数 n n n。
第二行 n n n 个数,表示集合 S S S。
第三行一个数 m m m,表示询问次数。
第四行 m m m 个数,表示每一次询问的 k k k。
输出格式
输出 m m m 行,对应每一次询问的答案,第 k k k 小的异或和。如果集合 S S S 的所有非空子集中,不同的异或和数量不足 k k k,输出 −1 -1 −1。
样例
样例输入
3 1 2 3 5 1 2 3 4 5
样例输出
0 1 2 3 -1
数据范围与提示
1≤n,m≤10^5,0≤Si≤250,0≤Si≤250
题解
要把线性基求出来后再消下元
对于询问,把k二进制拆分再求即可
代码
//by 减维 #include<set> #include<map> #include<ctime> #include<cmath> #include<queue> #include<bitset> #include<vector> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define ll long long #define il inline #define db double #define rg register #define mpr make_pair #define maxn 100005 #define eps 1e-8 #define inf (1<<30) #define pi 3.1415926535897932384626L using namespace std; inline int read() { int ret=0;bool fla=0;char ch=getchar(); while((ch<'0'||ch>'9')&&ch!='-')ch=getchar(); if(ch=='-'){fla=1;ch=getchar();} while(ch>='0'&&ch<='9'){ret=ret*10+ch-'0';ch=getchar();} return fla?-ret:ret; } int n,m,cnt; ll p[65],bin[65],a[65]; int main() { n=read();int pd=0; bin[0]=1;for(int i=1;i<=62;++i) bin[i]=bin[i-1]<<1; for(int i=1;i<=n;++i) { ll x;scanf("%lld",&x); for(int j=62;j>=0;--j) if(x&bin[j]){ if(!p[j]){p[j]=x;break;} x^=p[j]; } if(!x) pd=1; } for(int i=62;i>=0;--i) for(int j=i-1;j>=0;--j) if(bin[j]&p[i]) p[i]^=p[j]; for(int i=0;i<=62;++i) if(p[i]) a[cnt++]=p[i]; m=read(); ll k; for(int i=1;i<=m;++i) { scanf("%lld",&k);k-=pd; ll ans=0; if(k>bin[cnt]-1){puts("-1");continue;} for(int j=cnt-1;j>=0;--j) if(k&bin[j]) ans^=a[j]; printf("%lld\n",ans); } return 0; }
相关文章推荐
- LOJ114_k 大异或和_线性基
- 51nod1312 最大异或和
- ACM学习历程—CSU 1216 异或最大值(xor && 贪心 && 字典树)
- BZOJ 3261 最大异或和 && qwb VS 去污棒(可持久化01Trie)
- hdu4825-01字典树&&贪心&&经典&&异或最大-Xor Sum
- 51nod1312 最大异或和
- hdu5969-贪心&思维&证明-最大的异或
- LOJ114 k大(xiao)异或和(线性基)
- POJ 3764 The xor-longest( 树上异或前缀和&字典树求最大异或)
- bzoj3261最大异或和&&可持久化Trie树详解
- [POJ 1273] Drainage Ditches & 最大流Dinic模板
- DFS&BFS--最大乘积
- hdoj 1003 连续最大子数组 分治法 & dp法
- 二分图最大匹配的König定理及其证明
- poj1698 - Alice's Chance (最大流)
- 最大无法表示成px+qy(x>=0,y>=0)的数
- HDU 3549--Flow Problem 【最大流 && dinic】
- UVa 563 - Crimewave (拆点 + 最大流 & EK)
- BZOJ 4017&&2017 icpc 西安G 区间异或和
- 高斯消元&线性基模板