QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#73284 | #4654. Tree | Isrothy | AC ✓ | 961ms | 11164kb | C++23 | 7.5kb | 2023-01-23 14:39:35 | 2023-01-23 14:39:36 |
Judging History
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