zoukankan      html  css  js  c++  java
  • 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示例
    3
    1
    2
    3
    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
    ",ans);
    49     return 0;
    50 }
  • 相关阅读:
    [Re] SpringMVC-5(Converter+拦截器+国际化+异常处理)
    [Re] SpringMVC-4(数据绑定+数据格式化+数据校验)
    [Re] SpringMVC-3(视图解析+RESTful CRUD)
    [Re] SpringMVC-2(数据输出+源码流程)
    常用SQL优化
    JAVA 中的标准注解
    linux第一发
    easyui js取消选中 Tree 指定节点
    axis1.4 服务端获取请求报文报文和客户端获取请求报文和响应报文
    对于两个实体类属性值的合并,java实现
  • 原文地址:https://www.cnblogs.com/SilverNebula/p/7136270.html
Copyright © 2011-2022 走看看