• 线性基学习笔记 / 洛谷 P3812 【线性基】【贪心】


    线性基学习笔记

    前置芝士:

    假设有 a 1 ⃗ \vec{a_1} a1 a 2 ⃗ \vec{a_2} a2 ⋯ \cdots a n ⃗ \vec{a_n} an n n n 个向量所构成的向量组。

    然后定义一个常数组 c 1 c_1 c1 c 2 c_2 c2 c 3 c_3 c3 ⋯ \cdots c n c_n cn,让他们两两相乘,得到一个子空间 c 1 a 1 ⃗ c_1\vec{a_1} c1a1 c 2 a 2 ⃗ c_2\vec{a_2} c2a2 c 3 a 3 ⃗ c_3\vec{a_3} c3a3 ⋯ \cdots c n a n ⃗ c_n\vec{a_n} cnan 。其中 a n ∈ N a_n\in \textbf{N} anN

    假设一个向量组 a 1 , a 2 , a 3 , ⋯   , a n a_1,a_2,a_3,\cdots,a_n a1,a2,a3,,an 和另外的一个向量组 b 1 , b 2 , b 3 , ⋯   , b n b_1,b_2,b_3,\cdots,b_n b1,b2,b3,,bn 可以用上面的方法互相转换,那么他们是等价的。


    给定一个向量组 a 1 , a 2 , a 3 , ⋯   , a n a_1,a_2,a_3,\cdots,a_n a1,a2,a3,,an,现在要求求出一组他们的基。

    需要使用高斯等消元法来求解。

    当使用高斯消元消完某一列的时候,会形成一个三角形,类似于 ┕图 1 1 1┑,这个三角一定是线性无关的。原因,这里面的任意一个向量无法被其他向量表示。

    容易发现时间复杂度为 O ( n 3 ) O(n^3) O(n3)


    对于任意的一组向量 { x ⃗ 1 , x ⃗ 2 . x ⃗ 3 , ⋯   , x ⃗ n } \{\vec x_1,\vec x_2.\vec x_3,\cdots,\vec x_n\} {x 1,x 2.x 3,,x n},他都可以用上面所述的方法生成一个东西叫做子空间,这个子空间里面的任意基底都是等价的。

    重要:假设有一个向量组 { x ⃗ 1 , x ⃗ 2 , x ⃗ 3 ⋯ x ⃗ n } \{\vec x_1,\vec x_2,\vec x_3\cdots\vec x_n\} {x 1,x 2,x 3x n},其最大线性无关组的大小一定是小于等于他的维度的。假设维度为 63 63 63,那么 63 63 63 个向量构成的向量组可以代替这 n n n 个向量组。线性基的重中之重

    大量优化需要使用的时间。


    例题 洛谷 P3812

    给定 n n n 个整数,求在这些数中选取多少个数让异或和最大。 1 ≤ n ≤ 50 1\le n\le 50 1n50 0 ≤ a i ≤ 2 50 0\le a_i\le 2^{50} 0ai250

    实际上就是求最大的生成子空间。

    暴力时间复杂度 O ( 2 n ) O(2^n) O(2n),明显超时。

    首先找到 n n n 个向量的线性基,大约有 50 50 50 个有用的。

    然后进行贪心,将所有的向量的线性基进行异或就是答案。

    #include 
    #define int long long
    
    using namespace std;
    
    int a[100];
    
    signed main() {
      int n;
      cin >> n;
      for (int i = 0; i < n; i ++)
        cin >> a[i];
      int k = 0;
      for (int i = 50; i >= 0; i --) {
        for (int j = k; j < n; j ++)
          if (a[j] >> i & 1) {
            swap (a[j], a[k]);
            break;
          }
        if (a[k] >> i & 1) {
          for (int j = 0; j < n; j ++)
            if (j != k)
              if (a[j] >> i & 1)
                a[j] ^= a[k];
          k ++;
          if (k >= n)
            break;
        }
      }
      int res = 0;
      for (int i = 0; i < k; i ++)
        res ^= a[i];
      cout << res << '\n';
      return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    AC Record


    1 1 1在这里插入图片描述

    其中黑色框好的为非 0 0 0 数,其他的 0 0 0

  • 相关阅读:
    14:00面试,14:06就出来了,问的问题有点变态。。。
    Kafka + Kraft 集群搭建教程,附详细配置及自动化安装脚本
    Ubuntu下安装Teamviewer所遇certificates.crt CRLfile: none问题
    苹果手机适配Xcode14及iOS 16操作系统
    WPF 控件模板
    深圳xxx公司测试岗位企业面试题
    C++日期类实现(联系类和对象)
    [go][转载]vscode配置完go跑个helloworld例子
    硕士课程 可穿戴设备之作业一
    c++ openssl实现https
  • 原文地址:https://blog.csdn.net/lxylluvio/article/details/126548083