QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#73284#4654. TreeIsrothyAC ✓961ms11164kbC++237.5kb2023-01-23 14:39:352023-01-23 14:39:36

Judging History

你现在查看的是最新测评结果

  • [2023-08-10 23:21:45]
  • System Update: QOJ starts to keep a history of the judgings of all the submissions.
  • [2023-01-23 14:39:36]
  • 评测
  • 测评结果:AC
  • 用时:961ms
  • 内存:11164kb
  • [2023-01-23 14:39:35]
  • 提交

answer

#include <algorithm>
#include <cassert>
#include <iostream>
#include <iterator>
#include <optional>
#include <vector>

const int MOD = 1e9 + 7;

long long ex_gcd(long long a, long long b, long long &x, long long &y) {
    if (b == 0) {
        x = 1;
        y = 0;
        return a;
    }
    long long d = ex_gcd(b, a % b, y, x);
    y -= a / b * x;
    return d;
}

long long inv(long long a, long long MOD = 1e9 + 7) {
    long long x, y;
    a = (a + MOD) % MOD;
    ex_gcd(a, MOD, x, y);
    return (x % MOD + MOD) % MOD;
}

struct Matrix : public std::vector<std::vector<long long>> {
    static const int MOD = 1e9 + 7;
    size_t n, m;
    using std::vector<std::vector<long long>>::vector;
    Matrix(size_t n, size_t m) : n(n), m(m) {
        resize(n);
        for (int i = 0; i < n; ++i) {
            (*this)[i].resize(m);
        }
    }

    Matrix argument(std::vector<long long> v) const {
        assert(n == v.size());
        Matrix res(n, m + 1);
        for (int i = 0; i < n; ++i) {
            for (int j = 0; j < m; ++j) {
                res[i][j] = (*this)[i][j];
            }
            res[i][m] = v[i];
        }
        return res;
    }

    Matrix argument(Matrix B) const {
        assert(n == B.n);
        Matrix res(n, m + B.m);
        for (int i = 0; i < n; ++i) {
            for (int j = 0; j < m; ++j) {
                res[i][j] = (*this)[i][j];
            }
            for (int j = 0; j < B.m; ++j) {
                res[i][m + j] = B[i][j];
            }
        }
        return res;
    }

    Matrix transpose() const {
        Matrix res(m, n);
        for (int i = 0; i < n; ++i) {
            for (int j = 0; j < m; ++j) {
                res[j][i] = (*this)[i][j];
            }
        }
        return res;
    }

    Matrix remove_column(size_t k) const {
        assert(m != 1 && k < m);
        Matrix res(n, m - 1);
        for (int i = 0; i < n; ++i) {
            for (int j = 0; j < m - 1; ++j) {
                res[i][j] = (*this)[i][j < k ? j : j + 1];
            }
        }
        return res;
    }
    Matrix remove_row(size_t k) const {
        assert(n != 1 && k < n);
        Matrix res(n - 1, m);
        for (int i = 0; i < n - 1; ++i) {
            for (int j = 0; j < m; ++j) {
                res[i][j] = (*this)[i < k ? i : i + 1][j];
            }
        }
        return res;
    }

    long long determinate() const {
        assert(n == m);
        Matrix tmp = *this;
        long long res = 1;
        for (int i = 0; i < n; ++i) {
            for (int j = i + 1; j < n; ++j) {
                while (tmp[j][i] != 0) {
                    long long t = tmp[i][i] / tmp[j][i];
                    for (int k = i; k < n; ++k) {
                        tmp[i][k] = (tmp[i][k] - t * tmp[j][k]) % MOD;
                    }
                    std::swap(tmp[i], tmp[j]);
                    res = -res;
                }
            }
            res = (res * tmp[i][i]) % MOD;
        }
        return res;
    }

    std::vector<std::vector<long long>> Gaussian_elimination(const std::vector<long long> &v) const {
        assert(n == v.size());
        std::vector<long long> v0(m);
        std::vector<int> p(m, -1), f;
        Matrix tmp = this->argument(v);
        for (int i = 0, pivot = 0; i < n; ++i) {
            while (pivot < m && tmp[i][pivot] == 0) {
                for (int j = i + 1; j < n; ++j) {
                    if (tmp[j][pivot] != 0) {
                        std::swap(tmp[i], tmp[j]);
                        break;
                    }
                }
                if (tmp[i][pivot] == 0) {
                    f.push_back(pivot);
                    ++pivot;
                }
            }
            if (pivot == m) {
                break;
            }
            long long t = inv(tmp[i][pivot], MOD);
            for (int j = pivot; j <= m; ++j) {
                tmp[i][j] = tmp[i][j] * t % MOD;
            }
            for (int j = 0; j < n; ++j) {
                if (i != j) {
                    long long s = tmp[j][pivot];
                    for (int k = pivot; k <= m; ++k) {
                        tmp[j][k] = (tmp[j][k] - tmp[i][k] * s) % MOD;
                    }
                }
            }
            p[i] = pivot;
            v0[pivot] = tmp[i][m];
            ++pivot;
        }
        std::vector<std::vector<long long>> res;
        res.push_back(v0);
        for (auto i: f) {
            std::vector<long long> v(m, 0);
            v[i] = 1;
            for (int j = 0; j < n; ++j) {
                if (i != j && p[j] != -1) {
                    v[p[j]] = -tmp[j][i];
                }
            }
            res.push_back(v);
        }
        return res;
    }
    std::optional<Matrix> inverse() const {
        assert(n == m);
        auto tmp = this->argument(Matrix::identity(n));
        for (int i = 0; i < n; ++i) {
            if (tmp[i][i] == 0) {
                for (int j = i + 1; j < n; ++j) {
                    if (tmp[j][i] != 0) {
                        std::swap(tmp[i], tmp[j]);
                        break;
                    }
                }
                if (tmp[i][i] == 0) {
                    return std::nullopt;
                }
            }
            long long t = inv(tmp[i][i], MOD);
            for (int j = i; j < 2 * n; ++j) {
                tmp[i][j] = tmp[i][j] * t % MOD;
            }
            for (int j = 0; j < n; ++j) {
                if (i != j) {
                    long long s = tmp[j][i];
                    for (int k = i; k < 2 * n; ++k) {
                        tmp[j][k] = (tmp[j][k] - tmp[i][k] * s) % MOD;
                    }
                }
            }
        }
        Matrix res(n, n);
        for (int i = 0; i < n; ++i) {
            for (int j = 0; j < n; ++j) {
                res[i][j] = tmp[i][j + n];
            }
        }
        return res;
    }
    static Matrix identity(size_t n) {
        Matrix res(n, n);
        for (int i = 0; i < n; ++i) {
            res[i][i] = 1;
        }
        return res;
    }
    static Matrix zero(size_t n) {
        return {n, n};
    }
};
int main() {
    int _;
    for (scanf("%d", &_); _ != 0; --_) {
        int n, m;
        scanf("%d%d", &n, &m);
        if (n == 1) {
            puts("1");
            continue;
        }
        Matrix mat(n, n);
        for (int i = 0; i < m; ++i) {
            int u, v;
            scanf("%d%d", &u, &v);
            --u, --v;
            mat[u][v] -= 1;
            mat[v][v] += 1;
        }
        auto x = mat.Gaussian_elimination(std::vector<long long>(n, 0))[1];
        auto y = mat.transpose().Gaussian_elimination(std::vector<long long>(n, 0))[1];
        auto none_zero = [](int x) {
            return x != 0;
        };
        int i = (int) (std::find_if(x.begin(), x.end(), none_zero) - x.begin());
        int j = (int) (std::find_if(y.begin(), y.end(), none_zero) - y.begin());
        auto tx = inv(x[i]);
        auto ty = inv(y[j]);
        for (int k = 0; k < n; ++k) {
            x[k] = x[k] * tx % MOD;
            y[k] = y[k] * ty % MOD;
        }
        auto det = mat.remove_column(i).remove_row(j).determinate();
        if ((i + j) & 1) {
            det = -det;
        }
        for (int k = 0; k < n; ++k) {
            long long ans = det * x[k] % MOD * y[k] % MOD;
            printf("%lld ", (ans + MOD) % MOD);
        }
        puts("");
    }
    return 0;
}

Details

Tip: Click on the bar to expand more detailed information

Test #1:

score: 100
Accepted
time: 961ms
memory: 11164kb

input:

100
7 12
1 3
2 1
1 4
5 1
4 7
6 5
2 3
4 6
3 1
6 4
7 1
1 2
2 2
2 1
1 2
50 49
49 29
41 33
41 48
27 46
41 36
9 1
41 7
17 12
23 10
8 15
32 6
21 45
18 40
49 21
41 17
41 8
2 35
17 16
38 31
13 5
32 20
36 3
25 18
29 47
29 37
15 23
11 13
29 9
47 44
29 39
41 27
25 28
36 25
19 42
27 38
45 34
15 19
14 24
11 43
1...

output:

2 3 1 4 2 6 2 
1 1 
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 
1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
1 0 
850518977 850518977 850518977 850518977 850518977 850518977 850518977 8...

result:

ok 100 lines