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
  1. 第一行一个整数N,且1<=N<=50
  2. 接下来N行每行一个整数S[i],且0<=S[i]<=1,000,000,000,000,000 (10^15)
Output
  1. 一个整数,即最后集合可能的最大值SUM
Input示例
  1. 3
  2. 1
  3. 2
  4. 3
Output示例
  1. 8

题解

处理出来线性基直接求得结果即可

代码

  1. //by 减维
  2. #include<set>
  3. #include<map>
  4. #include<ctime>
  5. #include<cmath>
  6. #include<queue>
  7. #include<bitset>
  8. #include<vector>
  9. #include<cstdio>
  10. #include<cstring>
  11. #include<iostream>
  12. #include<algorithm>
  13. #define ll long long
  14. #define il inline
  15. #define db double
  16. #define rg register
  17. #define mpr make_pair
  18. #define maxn 105
  19. #define eps 1e-8
  20. #define inf (1<<30)
  21. #define pi 3.1415926535897932384626L
  22. using namespace std;
  23.  
  24. inline int read()
  25. {
  26. int ret=;bool fla=;char ch=getchar();
  27. while((ch<''||ch>'')&&ch!='-')ch=getchar();
  28. if(ch=='-'){fla=;ch=getchar();}
  29. while(ch>=''&&ch<=''){ret=ret*+ch-'';ch=getchar();}
  30. return fla?-ret:ret;
  31. }
  32.  
  33. int n,cnt;
  34. ll mx,ans,a[maxn],b[maxn],p[],bin[];
  35.  
  36. int main()
  37. {
  38. n=read();
  39. bin[]=;for(int i=;i<=;++i) bin[i]=bin[i-]<<;
  40. for(int i=;i<=n;++i) scanf("%lld",&a[i]),b[i]=a[i];
  41. for(int i=;i<=n;++i)
  42. for(int j=;j>=;--j)
  43. if(a[i]&bin[j])
  44. if(!p[j]){p[j]=a[i];break;}
  45. else a[i]^=p[j];
  46. for(int i=;i>=;--i)
  47. for(int j=i-;j>=;--j)
  48. if(p[i]&bin[j]) p[i]^=p[j];
  49. for(int i=;i>=;--i)
  50. if(p[i])
  51. {
  52. if((mx^p[i])>mx) mx^=p[i];
  53. cnt++;
  54. }
  55. ans+=mx*(n-cnt+);
  56. cnt--;
  57. for(int i=;cnt&&i<=;i++)
  58. if(p[i]) ans+=(mx^p[i]),cnt--;
  59. printf("%lld",ans);
  60. return ;
  61. }

#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。

样例

样例输入

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

样例输出

  1. 0
  2. 1
  3. 2
  4. 3
  5. -1

数据范围与提示

1≤n,m≤10^5,0≤Si≤250​​,0≤S​i​​≤2​50​​

题解

要把线性基求出来后再消下元

对于询问,把k二进制拆分再求即可

代码

  1. //by 减维
  2. #include<set>
  3. #include<map>
  4. #include<ctime>
  5. #include<cmath>
  6. #include<queue>
  7. #include<bitset>
  8. #include<vector>
  9. #include<cstdio>
  10. #include<cstring>
  11. #include<iostream>
  12. #include<algorithm>
  13. #define ll long long
  14. #define il inline
  15. #define db double
  16. #define rg register
  17. #define mpr make_pair
  18. #define maxn 100005
  19. #define eps 1e-8
  20. #define inf (1<<30)
  21. #define pi 3.1415926535897932384626L
  22. using namespace std;
  23.  
  24. inline int read()
  25. {
  26. int ret=;bool fla=;char ch=getchar();
  27. while((ch<''||ch>'')&&ch!='-')ch=getchar();
  28. if(ch=='-'){fla=;ch=getchar();}
  29. while(ch>=''&&ch<=''){ret=ret*+ch-'';ch=getchar();}
  30. return fla?-ret:ret;
  31. }
  32.  
  33. int n,m,cnt;
  34. ll p[],bin[],a[];
  35.  
  36. int main()
  37. {
  38. n=read();int pd=;
  39. bin[]=;for(int i=;i<=;++i) bin[i]=bin[i-]<<;
  40. for(int i=;i<=n;++i)
  41. {
  42. ll x;scanf("%lld",&x);
  43. for(int j=;j>=;--j)
  44. if(x&bin[j]){
  45. if(!p[j]){p[j]=x;break;}
  46. x^=p[j];
  47. }
  48. if(!x) pd=;
  49. }
  50. for(int i=;i>=;--i)
  51. for(int j=i-;j>=;--j)
  52. if(bin[j]&p[i]) p[i]^=p[j];
  53. for(int i=;i<=;++i) if(p[i]) a[cnt++]=p[i];
  54. m=read();
  55. ll k;
  56. for(int i=;i<=m;++i)
  57. {
  58. scanf("%lld",&k);k-=pd;
  59. ll ans=;
  60. if(k>bin[cnt]-){puts("-1");continue;}
  61. for(int j=cnt-;j>=;--j)
  62. if(k&bin[j]) ans^=a[j];
  63. printf("%lld\n",ans);
  64. }
  65. return ;
  66. }

【线性基】51nod1312 最大异或和&LOJ114 k大异或和的更多相关文章

  1. LOJ114 k大异或和

    传送门 (vjudge和hdu也有但是我觉得LOJ好看!而且限制少!) 不过本题描述有误,应该是k小. 首先我们需要对线性基进行改造.需要把每一位改造成为,包含最高位的能异或出来的最小的数. 为啥呢? ...

  2. LOJ.114.K大异或和(线性基)

    题目链接 如何求线性基中第K小的异或和?好像不太好做. 如果我们在线性基内部Xor一下,使得从高到低位枚举时,选base[i]一定比不选base[i]大(存在base[i]). 这可以重构一下线性基, ...

  3. Loj 114 k大异或和

    Loj 114 k大异或和 构造线性基时有所变化.试图构造一个线性基,使得从高到低位走,异或上一个非 \(0\) 的数,总能变大. 构造时让任意两个 \(bas\) 上有值的 \(i,j\) ,满足 ...

  4. [LOJ#114]k 大异或和

    [LOJ#114]k 大异或和 试题描述 这是一道模板题. 给由 n 个数组成的一个可重集 S,每次给定一个数 k,求一个集合 T⊆S,使得集合 T 在 S 的所有非空子集的不同的异或和中,其异或和  ...

  5. LibreOJ #114. k 大异或和

    二次联通门 : LibreOJ #114. k 大异或和 /* LibreOJ #114. k 大异或和 WA了很多遍 为什么呢... 一开始读入原数的时候写的是for(;N--;) 而重新构造线性基 ...

  6. LOJ114 k大(xiao)异或和(线性基)

    构造线性基后将其消至对任意位至多只有一个元素该位为1.于是就可以贪心了,将k拆成二进制就好.注意check一下是否能异或出0. #include<iostream> #include< ...

  7. 【loj114】k大异或和 线性基+特判

    题目描述 给由 $n​$ 个数组成的一个可重集 $S​$ ,每次给定一个数 $k​$ ,求一个集合 $T⊆S​$ ,使得集合 $T​$ 在 $S​$ 的所有非空子集的不同的异或和中,其异或和 $T_1 ...

  8. 第k大异或值

    这道题与2018年十二省联考中的异或粽子很相像,可以算作一个简易版: 因为这不需要可持久化: 也就是说求任意两个数异或起来的第k大值: 首先把所有数放进trie里. 然后二分答案,枚举每个数,相应地在 ...

  9. hdu 3949 第k大异或组合

    题意: 给你一些数,其中任选一些数(大于等于一个),那么他们有一个异或和. 求所有这样的异或和的第k小. 我们可以将每一位看成一维,然后就是给我们n个60维的向量,求它们线性组合后得到的向量空间中,第 ...

随机推荐

  1. 运行自己的shell脚本

    shell脚本可以直接./**.sh,也可以bash **.sh 我用./**.sh运行自己写的一个脚本,会出现如下的错误: bnrc@bnrc:~$ ./pixel.sh bash: ./pixel ...

  2. Python实现注册和登录

    一.注册账号需要实现的功能 1.输入:用户名,密码,密码确认 2.限制1:输入的账号和密码不能为空 3.限制2:两次输入密码必须一致 4.限制3:用户名不能重复 5.限制4:错误次数为4次 6.用字典 ...

  3. bootstrap table 自定义checkbox样式

    //css <style> .checkbox-custom { position: relative; padding: 0 15px 0 25px; margin-bottom: 7p ...

  4. dom事件操作例题,电子时钟,验证码,随机事件

    dom事件操作 当事件发生时,可以执行js 例子: 当用户点击时,会改变<h1>的内容: <h1 onClick="this.innerHTML='文本更换'"& ...

  5. Oracle 换行符 空格符 回车符

    ① 换行符 chr(10)② 回车符 chr(13) ③ 空格符 chr(9) 例1:效果对比.chr(10)在一个字段中换行显示一列数据,chr(13)同样是换行显示一行数据,chr(9)会显示一个 ...

  6. Linux 命令大全提供 500 多个 Linux 命令搜索

    Linux Command 在这里维持一个持续更新的地方 516 个 Linux 命令大全,内容包含 Linux 命令手册.详解.学习,值得收藏的 Linux 命令速查手册.请原谅我写了个爬虫,爬了他 ...

  7. jquery简易的三级导航

    <!DOCTYPE html> <html>     <head>         <meta charset="UTF-8">   ...

  8. js时间转换

    1. 将时间戳转换成日期格式 // 简单的一句代码 var date = new Date(时间戳); //获取一个时间对象 /** 1. 下面是获取时间日期的方法,需要什么样的格式自己拼接起来就好了 ...

  9. 20190103(GIL,池,阻塞,同步异步)

    GIL锁 什么是GIL GIL全局解释器锁,是防止多个线程在同一时间同时执行的.CPython解释器特有的一种互斥锁. 每一个py文件都会有自己的解释器,也就是说不同py文件的GIL都是独立的, ps ...

  10. day13内置函数

    内置函数 一.三元表达式 def max2(x,y): if x>y: return x else: return y res=max2(10,11) print(res) 三元表达式仅应用于: ...