线性基(25.10.5)

线性基

概述

使用特殊方法得到A的子集B,使B可以通过不同元素乘除加减得到A的每个元素,B是最简状态,称为A的线性基

可以去解决线性相关/无关的问题,(两个向量通过不同的加减变化会不会变成另一个数)

思考方向

  1. 发现题目中有存在使用不同元素乘除加减组合,考虑线性基
  2. 发现(最大)异或和的问题,尝试考虑线性基

普通异或线性基

贪心线性基

  1. 主要生成的B是所有元素异或和的可能不会有0
  2. 存储的是原数本身,所以需要再贪心一下才能再输出
  3. 本质是尝试一个数和其它的所有数异或和,看看能不能有新的位数出现
#include <bits/stdc++.h>
using namespace std;
#define ll long long
ll p[64];
int n;
void ins(ll x) {
    for (int i=63; i>=0; i--) {
        if (!(x>>i)) continue;
        if (!p[i]) {
            p[i] = x;
            break;
        }
        x^=p[i];
    }
}
int main() {
    cin>>n;
    ll a;
    for (int i=1; i<=n; i++) {
        cin>>a;
        ins(a);
    }
    ll ans=0;
    for (int i=63; i>=0; i--) {
        ans = max(ans,ans^p[i]);
    }
    cout<<ans<<endl;
    return 0;
}

高斯消元线性基

  1. 把数已经消成了通解(如x1+x2+x3+x4化简后只存在单个主元),这样就可以直接操作

  2. 这里的只是把所有数的主元以梯形形式呈现,没有进一步的归一化操作,但是已经够用了

    初中生也能看懂的高斯消元算法!!_哔哩哔哩_bilibili

异或高斯消元线性基

#include <iostream>
using ull = unsigned long long;  // 定义无符号长整型,避免符号位干扰
constexpr int MAXN = 1e5 + 5;    // 最大数据量,1e5+5

// 辅助函数:判断num的第deg位是否为1(返回该位的值,0或2^deg)
ull deg(ull num, int deg) {
 return num & (1ull << deg);  // 1ull确保移位操作按64位无符号数处理
}

ull a[MAXN];  // 存储原始数据的数组,后续会被改造成线性基
using std::cin;
using std::cout;

int main() {
 cin.tie(nullptr)->sync_with_stdio(false);  // 关闭同步,加速输入输出
 int n;
 cin >> n;
 for (int i = 1; i <= n; ++i) cin >> a[i];  // 读入n个数据

 int row = 1;  // 记录当前构建的线性基行数(有效元素数)

 // 从最高位(63位)向最低位(0位)处理,构建线性基
 // ~col 等价于 col >= 0(当col=-1时,~col=0,循环结束)
 for (int col = 63; ~col && row <= n; --col) {
     // 寻找当前列(第col位)中,从row行开始第一个该位为1的数
     for (int i = row; i <= n; ++i) {
         if (deg(a[i], col)) {  // 找到第col位为1的数
             std::swap(a[row], a[i]);  // 将该数交换到当前行(row行)
             break;
         }
     }

     // 如果当前行的第col位为0,说明该位无法找到线性基元素,跳过该位
     if (!deg(a[row], col)) continue;

     // 消去其他行中第col位的1,确保只有row行在第col位为1(高斯消元核心)
     for (int i = 1; i <= n; ++i) {
         if (i == row) continue;  // 跳过当前行(保留线性基元素)
         if (deg(a[i], col)) {    // 若其他行的第col位为1
             a[i] ^= a[row];      // 用当前行消去该位的1
         }
     }
     ++row;  // 成功构建一行线性基,处理下一行
 }

 // 计算最大异或和:线性基中所有非零元素异或的结果
 ull ans = 0;
 for (int i = 1; i < row; ++i) {  // row-1是线性基的有效元素个数
     ans ^= a[i];
 }
 cout << ans << '\n';
 return 0;
}

实数高斯消元线性基

#include <iostream>
using ull = unsigned long long;  // 定义无符号长整型,避免符号位干扰
constexpr int MAXN = 1e5 + 5;    // 最大数据量,1e5+5

// 辅助函数:判断num的第deg位是否为1(返回该位的值,0或2^deg)
ull deg(ull num, int deg) {
    return num & (1ull << deg);  // 1ull确保移位操作按64位无符号数处理
}

ull a[MAXN];  // 存储原始数据的数组,后续会被改造成线性基
using std::cin;
using std::cout;

int main() {
    cin.tie(nullptr)->sync_with_stdio(false);  // 关闭同步,加速输入输出
    int n;
    cin >> n;
    for (int i = 1; i <= n; ++i) cin >> a[i];  // 读入n个数据

    int row = 1;  // 记录当前构建的线性基行数(有效元素数)

    // 从最高位(63位)向最低位(0位)处理,构建线性基
    // ~col 等价于 col >= 0(当col=-1时,~col=0,循环结束)
    for (int col = 63; ~col && row <= n; --col) {
        // 寻找当前列(第col位)中,从row行开始第一个该位为1的数
        for (int i = row; i <= n; ++i) {
            if (deg(a[i], col)) {  // 找到第col位为1的数
                std::swap(a[row], a[i]);  // 将该数交换到当前行(row行)
                break;
            }
        }

        // 如果当前行的第col位为0,说明该位无法找到线性基元素,跳过该位
        if (!deg(a[row], col)) continue;

        // 消去其他行中第col位的1,确保只有row行在第col位为1(高斯消元核心)
        for (int i = 1; i <= n; ++i) {
            if (i == row) continue;  // 跳过当前行(保留线性基元素)
            if (deg(a[i], col)) {    // 若其他行的第col位为1
                a[i] ^= a[row];      // 用当前行消去该位的1
            }
        }

        ++row;  // 成功构建一行线性基,处理下一行
    }

    // 计算最大异或和:线性基中所有非零元素异或的结果
    ull ans = 0;
    for (int i = 1; i < row; ++i) {  // row-1是线性基的有效元素个数
        ans ^= a[i];
    }
    cout << ans << '\n';
    return 0;
}

题目

P3812 【模板】线性基

一道普通模板

[P3857 TJOI2008] 彩灯 - 洛谷

发现存在两种状态相互异或和,所以考虑线性基

[P4570 BJWC2011] 元素 - 洛谷

发现题目需要去找序号之间的 异或线性不相关,考虑线性基,直接去存,可以保证线性不想关

[P3265 JLOI2015] 装备购买 - 洛谷

题目直接表明需要去找向量之间的线性不想关,所以延伸出实数向量的线性基(只能通过高斯消元写)(通过贪心的话难以向下实现)

以上均为线性基的模板题目

tip(25.10.5):目前线性基还有漏洞,没有进一步去完善,在NOIP之前准备补齐

posted @ 2025-10-05 09:10  Yuriha  阅读(0)  评论(0)    收藏  举报