线性基

定义

线性基用于解决类似于: "给定 n 个数, 取任意个数, 使得异或值最大"此类问题

本质上还是求出多个数最大和最小的异或和,由于给出的数目较大, 如果直接一一比较的话时间复杂度较大,可以通过线性基优化, 假如有 n 个, 其中最大的数二进制位数为 m 位, 那么线性基可以把原来的 2n 的组合优化到 2m, 一次的时间复杂度为 m. 虽然理论上有 2n 种组合, 但是由于: 任意两个数 a,b 做异或运算之后不会比他们两者的最高二进制位还要高, 所以 2n 种组合中最大的数也就是2m1 也就是异或结果会在: [0 ~ 2m1] 这个区间内

这里介绍一下什么是线性基, 举个形象的例子来说, A=[2,3,5,6,7] 那么它的任意组合有 2n1 种, 对 A 中所有的数做异或运算之后得到所有的可能性: [0,1,2,3,4,5,6,7]=8 种, A 中最大的数字二进制位是 3 位, 此时我们有个线性基 P=[5,2,1], 有 231=7 种, 注意线性基不能处理异或为 0 的可能性, 故此时为 7, 注意, 线性基不是唯一的

算法

接下来考虑如何构造线性基, 下面通过分析两个例子
(1). 首先分析一种特例, A 中所有的元素的二进制位均不同, 那么 A 自身就是一个线性基, 例如 A=[1,3,9]=[1,11,1001], 那么很明显是 1,2,4 位, 均不同, 此时 A 自己就是自己的线性基, 因为如果我需要异或出一个长度为 4 的数, 那么 P 中必须有长度为 4 的数, 对于其他数字同理
(2). 对于 A 中的数字较为繁杂, 含有相同位数的数字, 我们这样处理, 对于任意相同的数字, 直接异或即可. 先讨论两个位数相同的线性基构造. 设 A=[a1,a2] 且两者二进制位数相同, 那么其线性基为: P=[a1,a1a2], 下面给出证明: 对于 A=[a1,a2] 的组合: [a1,a2,a1a2] , 而 P 的组合为: [a1,a1a2,a1a1a2=0a2=a2], 由此可见, 两者相同, 那么我们对于相同位的直接做异或处理即可.

  1. 最小异或和
    由于最小异或和就一个值, 那么不是 0 就是位数最小的那个数字
  2. 最大异或和
    考虑贪心, 对于每一位的数字, 我们直接做异或看看是否增大, 若增大, 我们就直接加进去, 为什么这样是对的? 因为我们从大到小开始, 对于最大的, 肯定不会存在一个其它的数可以到达最高位. 对于次大的, 若异或后对答案有益, 我们就异或, 因为不会存在一个更大的数可以使答案更优, 换句话说, 比它小的元素任意的组合都不会比它大.

例题

下面给出例题: 线性基

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e6 + 10, mod = 1e9 + 7;
signed main()
{
    std::ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    int n; cin >> n;
    vector<int> p(65);
    bool zero;
    auto insert = [&](int x) -> void{
        for(int i = 61; i >= 1; i--){
            if(x >> (i - 1)){
                if(p[i] == 0){
                    p[i] = x;
                    return;
                }
                else x ^= p[i];
            }   
        }
        zero = true;
    };
    for(int i = 1; i <= n; i++){
        int x; cin >> x;
        insert(x);
    }
    int res = 0;
    for(int i = 61; i >= 1; i--){
        res = max(res, res ^ p[i]);
    }
    cout << res << '\n';
    return 0;
}
posted @   o-Sakurajimamai-o  阅读(16)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
历史上的今天:
2023-07-30 砍竹子
2023-07-30 李白打酒
2023-07-30 测试1
2023-07-30 #878
-- --
点击右上角即可分享
微信分享提示