• 【线性基】51nod1312 最大异或和&LOJ114 k大异或和


    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
    3
    Output示例
    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 TS,使得集合 T T T 在 S S S 的所有非空子集的不同的异或和中,其异或和 T1xorT2xorxorT|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​​,0Si​​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
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    job_queue_processes参数讲解
    Oracle trunc()函数的用法
    JSON字符串转JavaBean,net.sf.ezmorph.bean.MorphDynaBean cannot be cast to ……
    javax.swing.JList 设置分割线
    清除SVN版本控制文件
    MyEclipse SVN安装方法
    ExtJs xtype类型介绍
    Android中的“再按一次返回键退出程序”实现
    Android之NetworkOnMainThreadException异常
    HDU 3613 Best Reward
  • 原文地址:https://www.cnblogs.com/rir1715/p/8581476.html
Copyright © 2020-2023  润新知