线性代数模板

线性代数模板

高斯消元法

/*
 * 高斯-约旦消元法
 * 可以修改为解异或方程组 修改策略为
 * a+b -> a^b
 * a-b -> a^b
 * a*b -> a&b
 * a/b -> a*(b==1)
 * */
void gauss(int n) {
    vector<bool> vis(n, false);
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < n; ++j) {
            if (vis[j]) continue;
            if (fabs(a[j][i]) > eps) {
                vis[i] = true;
                for (int k = 0; k <= n; ++k) swap(a[i][k], a[j][k]);
                break;
            }
        }
        if (fabs(a[i][i]) < eps) continue;
        for (int j = 0; j <= n; ++j) {
            if (i != j && fabs(a[j][i]) > eps) {
                double res = a[j][i] / a[i][i];
                for (int k = 0; k <= n; ++k) a[j][k] -= a[i][k] * res;
            }
        }
    }
}

int check(int n) { // 解系检测
    int status = 1;
    for (int i = n - 1; i >= 0; --i) {
        if (fabs(a[i][i]) < eps && fabs(a[i][n]) > eps) return -1; // 无解
        if (fabs(a[i][i]) < eps && fabs(a[i][n]) < eps) status = 0; // 无穷解
        ans[i] = a[i][n] / a[i][i];
        if (fabs(ans[i]) < eps) ans[i] = 0;
    }
    return status; // 唯一解或无穷解
}

bitset版高斯消元法

const int SIZE = 1001;
bitset<SIZE> a[SIZE];
int ans[SIZE];
void gauss(int n) { // bitset版高斯消元 用于求解异或线性方程组
    bitset<SIZE> vis;
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < n; ++j) {
            if (vis[j]) continue;
            if (a[j][i]) {
                vis.set(i);
                swap(a[i], a[j]);
                break;
            }
        }
        if (!a[i][i]) continue;
        for (int j = 0; j <= n; ++j) {
            if (i != j && (a[j][i] & a[i][i])) {
                a[j] ^= a[i];
            }
        }
    }
}

矩阵树定理/任意模数行列式求值

/*
 * 矩阵树定理
 * 有向图:若 u->v 有一条权值为 w 的边 基尔霍夫矩阵 a[v][v] += w, a[v][u] -= w
 * 生成树数量为除去 根所在行和列 后的n-1阶行列式的值
 * 无向图:若 u->v 有一条权值为 w 的边 基尔霍夫矩阵 a[v][v] += w, a[v][u] -= w, a[u][u] += w, a[u][v] -= w
 * 生成树数量为除去 任意一行和列 后的n-1阶行列式的值
 * 无权图则边权默认为1
 * */
typedef long long ll;
typedef unsigned long long u64;
int a[SIZE][SIZE];
int gauss(int a[][SIZE], int n) { // 任意模数求行列式 O(n^2(n + log(mod)))
    int ans = 1;
    for (int i = 1; i <= n; i++) {
        int* x = 0, * y = 0;
        for (int j = i; j <= n; j++) {
            if (a[j][i] && (x == NULL || a[j][i] < x[i])) {
                x = a[j];
            }
        }
        if (x == 0) {
            return 0;
        }
        for (int j = i; j <= n; j++) {
            if (a[j] != x && a[j][i]) {
                y = a[j];
                for (;;) {
                    int v = md - y[i] / x[i], k = i;
                    for (; k + 3 <= n; k += 4) {
                        y[k + 0] = (y[k + 0] + u64(x[k + 0]) * v) % md;
                        y[k + 1] = (y[k + 1] + u64(x[k + 1]) * v) % md;
                        y[k + 2] = (y[k + 2] + u64(x[k + 2]) * v) % md;
                        y[k + 3] = (y[k + 3] + u64(x[k + 3]) * v) % md;
                    }
                    for (; k <= n; ++k) {
                        y[k] = (y[k] + u64(x[k]) * v) % md;
                    }
                    if (!y[i]) break;
                    swap(x, y);
                }
            }
        }
        if (x != a[i]) {
            for (int k = i; k <= n; k++) {
                swap(x[k], a[i][k]);
            }
            ans = md - ans;
        }
        ans = 1LL * ans * a[i][i] % md;
    }
    return ans;
}

线性基

struct linearBasis {
    /* 线性基性质:
     * 1.若a[i]!=0(即主元i存在)
     *   则线性基中只有a[i]的第i位是1(只存在一个主元)
     *   且此时a[i]的最高位就是第i位
     * 2.将数组a插入线性基 假设有|B|个元素成功插入
     *   则数组a中每个不同的子集异或和都出现 2^(n-|B|) 次
     * */
    static const int MAXL = 60;
    long long a[MAXL + 1];
    int id[MAXL + 1];
    int zero; 
    /* 0的标志位 =1则表示0可以被线性基表示出来
     * 求第k大元素时 需要注意题意中线性基为空时是否可以表示0
     * 默认不可以表示 有必要时进行修改即可
     * */
    linearBasis() {
        zero = 0;
        fill(a, a + MAXL + 1, 0);
    }
    long long& operator [] (int k) { return a[k]; }
    bool insert(long long x) {
        for (int j = MAXL; ~j; j--) {
            if (!(x & (1LL << j))) { // 如果 x 的第 j 位为 0,则跳过
                continue;
            }
            if (a[j]) { // 如果 a[j] != 0,则用 a[j] 消去 x 的第 j 位上的 1
                x ^= a[j];
            } else { // 找到插入位置
                for (int k = 0; k < j; k++) {
                    if (x & (1LL << k)) { // 如果x存在某个低位线性基的主元k则消去
                        x ^= a[k];
                    }
                }
                for (int k = j + 1; k <= MAXL; k++) {
                    if (a[k] & (1LL << j)) { // 如果某个高位线性基存在主元j则消去
                        a[k] ^= x;
                    }
                }
                a[j] = x;
                return true;
            }
        }
        zero = 1;
        return false;
    }
    long long query_max() { // 最大值
        long long res = 0;
        for (int i = MAXL; ~i; i--) {
            res ^= a[i];
        }
        return res;
    }
    long long query_max(long long x) { // 线性基异或x的最大值
        for (int i = MAXL; ~i; i--) {
            if ((x ^ a[i]) > x) {
                x ^= a[i];
            }
        }
        return x;
    }
    long long query_min() { // 最小值
        for (int i = 0; i < MAXL; i++) {
            if (a[i]) {
                return a[i];
            }
        }
        return -1; // 线性基为空
    }
    long long query_min(long long x) { // 线性基异或x的最小值
        for (int i = MAXL; ~i; i--) {
            if ((x ^ a[i]) < x) {
                x ^= a[i];
            }
        }
        return x;
    }
    int count(long long x) { // 元素 x 能否被线性基内元素表示
        int res = 0;
        vector<long long> b(MAXL + 1);
        for (int i = 0; i <= MAXL; i++) {
            b[i] = a[i];
        }
        res = this->insert(x);
        for (int i = 0; i <= MAXL; i++) {
            a[i] = b[i];
        }
        return !res; // 成功插入则无法表示 失败则可以表示
    }
    int size() { // 线性基有效元素数量
        int res = 0;
        for (int i = 0; i <= MAXL; i++) {
            if (a[i]) {
                res++;
            }
        }
        return res;
    }
    long long kth_element(long long k) { // 第k大元素
        vector<long long> b;
        for (int i = 0; i <= MAXL; i++) {
            if (a[i]) {
                b.push_back(a[i]);
            }
        }
        if (zero) {
            if (--k == 0) {
                return 0;
            }
        }
        if (k >= (1LL << this->size())) { // k超过了线性基可以表示的最大数量
            return -1;
        }
        long long res = 0;
        for (int i = 0; i <= MAXL; i++) {
            if (k & (1LL << i)) {
                res ^= b[i];
            }
        }
        return res;
    }
    long long rank(long long x) { // 元素x在线性基内的排名(默认不考虑0)
        vector<long long> b;
        for (int i = 0; i <= MAXL; i++) {
            if (a[i]) {
                b.push_back(1LL << i);
            }
        }
        long long res = 0;
        for (int i = 0; i < (int)b.size(); i++) {
            if (x & b[i]) {
                res |= (1LL << i);
            }
        }
        return res;
    }
    void clear() {
        zero = 0;
        fill(a, a + MAXL + 1, 0);
    }
};

线性基naive

struct simpleLinearBasis {
    int n;
    vector<long long> a;
    simpleLinearBasis(int n_ = 0) { n = n_, a.resize(n, 0); }
    long long& operator[] (int k) { return a[k]; }
    bool insert(int x) {
        for (int i = n - 1; ~i; i--) {
            if ((x >> i) & 1) {
                if (!a[i]) {
                    a[i] = x;
                    return true;
                }
                x ^= a[i];
            }
        }
        return false;
    }
};

bitset版线性基

static const int N = 501;
struct linearBasis {
    static const int MAXL = 500;
    bitset<N> bs[N];
    linearBasis() {
        for (int i = 0; i <= MAXL; i++) {
            bs[i].reset();
        }
    }
    bool insert(bitset<N> x) { // 插入向量x
        for (int j = MAXL; ~j; j--) {
            if (!x[j]) { // 如果 x 的第 j 位为 0,则跳过
                continue;
            }
            if (bs[j][j]) { // 如果 a[j] != 0,则用 a[j] 消去 x 的第 j 位上的 1
                x ^= bs[j];
            } else { // 找到插入位置
                for (int k = 0; k < j; k++) {
                    if (x[k]) { // 如果x存在某个低位线性基的主元k则消去
                        x ^= bs[k];
                    }
                }
                for (int k = j + 1; k <= MAXL; k++) {
                    if (bs[k][j]) { // 如果某个高位线性基存在主元j则消去
                        bs[k] ^= x;
                    }
                }
                bs[j] = x;
                return true;
            }
        }
        return false;
    }
};

线性基x高斯消元

// a数组存线性基,b数组存给定的向量
db a[MAXL][MAXL], b[MAXL][MAXL];
bool insert(int k) { // 询问一个向量 a[0,1,2,...,k-1] 能否被已有元素线性组合出来
    for (int i = 0; i < n; i++) {
        if (fabs(b[k][i]) < eps) continue;
        if (fabs(a[i][i]) > eps) {
            db div = b[k][i] / a[i][i];
            for (int j = 0; j < m; j++) {
                b[k][j] -= div * a[i][j];
            }
        } else {
            for (int j = 0; j < m; j++) {
                a[i][j] = b[k][j];
            }
            return true;
        }
    }
    return false;
}
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇