首页 > 代码库 > 51nod1312 最大异或和
51nod1312 最大异或和
题目来源: TopCoder
基准时间限制:1 秒 空间限制:131072 KB 分值: 320
有一个正整数数组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示例
3123
Output示例
8
数学问题 线性基 贪心
显然就是线性基。
假设我们需要k个数来搞出线性基,那么有n-k个数可以取到异或空间里的最大值max。
这k个数线性无关,为了使他们最大,我们先把它们消到尽可能小,再异或max。
↑把得到的n个数累加起来就是答案。
秒题三分钟,写题一小时?exm?
动态维护线性基看上去并没有问题,然而交上去无限WAWAWA。
然后突然意识到年初的时候和Sfailsth讨论过的问题:高斯消元得到的线性基向量一定是该位为1的所有可能得到的向量中最小的,而动态维护线性基得到不一定是最小的。
丢一个链接:http://www.cnblogs.com/SfailSth/p/6220328.html
于是手动把线性基向量消到最小,AC
1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 #include<cstdio> 5 #include<cmath> 6 #define LL long long 7 using namespace std; 8 const int mxn=65; 9 LL read(){10 LL x=0,f=1;char ch=getchar();11 while(ch<‘0‘ || ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();}12 while(ch>=‘0‘ && ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}13 return x*f;14 }15 int n;16 LL a[mxn],b[mxn],f[mxn];17 int main(){18 int i,j;19 n=read();20 for(i=1;i<=n;i++)a[i]=b[i]=read();21 for(i=1;i<=n;i++)22 for(j=62;j>=0;j--){23 if((b[i]>>j)&1){24 if(!f[j]){f[j]=b[i];break;}25 b[i]^=f[j];26 }27 }28 LL mx=0;int cnt=0;29 for(i=62;i>=0;i--)30 if(f[i]){31 if((mx^f[i])>mx){mx^=f[i];}32 cnt++;33 }34 LL ans=0;35 ans+=mx*(n-cnt+1);36 cnt--;37 for(i=0;cnt && i<=62;i++){38 if(f[i]){39 for(int j=i-1;j>=0;j--){40 if(f[j] && ((f[i]>>j)&1)){41 f[i]^=f[j];42 }43 }44 ans+=mx^f[i];45 cnt--;46 }47 }48 printf("%lld\n",ans);49 return 0;50 }
51nod1312 最大异或和
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。