zoukankan      html  css  js  c++  java
  • 洛谷P3812 【模板】线性基

    P3812 【模板】线性基

    题目传送门

    构造过程

    用b[]来存线性基,将各个元素转化为二进制来看,b[i]里存的是最高位的1在i位的数,如果b[i]里已经存了数了,则将这个数与b[i]异或把异或后的值按照这种方法继续往下存入,直到全部存完。

    因为线性基是由原集合构造的,显然原集合里的数可以异或出线性基里的所有数,又因为ab=c,则ac=b,所以原集合中的所有数也可以由线性基构造出来。又因为a^a=0,所以显然线性基可以构造出原数组可以构造的所有异或和。

    为了求最大值,我们从最高位1最大的开始往小的异或,如果异或后会变大,则异或,变小则舍弃,最后得出的即为最大值。因为我们异或的数的最高位1递减,如果变大说明下一个异或的数的最高位1对应的位置上,我们的答案从0变为了1,否则是从1变为了0,如果是从1变为0,后面的异或不能使这个0重新变为1,只会改变后面的位数,这个损失比后面所以可能增加的都大,所以不能选。

    代码如下

    #include <bits/stdc++.h>
    #define INF 0x3f3f3f3f
    using namespace std;
    typedef long long ll;
    
    ll s[55], b[70];
    
    int main()
    {
        int n;
        cin >> n;
        for(int i = 1; i <= n; i ++)
            cin >> s[i];
        for(int i = 1; i <= n; i ++){
            for(int j = 50; j >= 0; j --){
                if((s[i] >> j) & 1){
                    if(b[j])
                        s[i] ^= b[j];
                    else {
                        b[j] = s[i];
                        break;
                    }
                }
            }
        }
        ll ans = 0;
        for(int i = 50; i >= 0; i --){
            if((ans ^ b[i]) > ans)
                ans ^= b[i];
        }
        cout << ans << endl;
    }
    
  • 相关阅读:
    RxJava系列7(最佳实践)
    异步编程 z
    利用WCF的双工通讯实现一个简单的心跳监控系统 z
    c#深拷贝
    MEF load plugin from directory
    C# 文件操作 把文件读取到字节数组
    code md5
    gridview转成EXCEL文件保存(多页)
    Getting started with SciPy for .NET
    IronPython调用C# DLL函数方法
  • 原文地址:https://www.cnblogs.com/whisperlzw/p/11234719.html
Copyright © 2011-2022 走看看