QOJ.ac
QOJ
ID | 题目 | 提交者 | 结果 | 用时 | 内存 | 语言 | 文件大小 | 提交时间 | 测评时间 |
---|---|---|---|---|---|---|---|---|---|
#641924 | #6161. 作业题 | Elegia | 100 ✓ | 3ms | 5000kb | C++14 | 8.5kb | 2024-10-15 03:19:56 | 2024-10-15 03:19:56 |
Judging History
answer
#include <cassert>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <ctime>
#include <cctype>
#include <algorithm>
#include <valarray>
#include <random>
#include <bitset>
#include <queue>
#include <functional>
#include <set>
#include <map>
#include <unordered_map>
#include <vector>
#include <chrono>
#include <iostream>
#include <limits>
#include <numeric>
#define LOG(FMT...) fprintf(stderr, FMT)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
template<class T>
istream &operator>>(istream &is, vector<T> &v) {
for (T &x : v)
is >> x;
return is;
}
template<class T>
ostream &operator<<(ostream &os, const vector<T> &v) {
if (!v.empty()) {
os << v.front();
for (int i = 1; i < v.size(); ++i)
os << ' ' << v[i];
}
return os;
}
const uint Mod = 998244353;
constexpr uint norm(uint v) { return v >= Mod ? v - Mod : v; }
struct Z {
uint v;
constexpr Z(uint v = 0) : v(v) {}
inline constexpr Z operator+(const Z &rhs) const { return norm(v + rhs.v); }
inline constexpr Z operator-(const Z &rhs) const { return norm(v + Mod - rhs.v); }
inline constexpr Z operator-() const { return norm(Mod - v); }
inline constexpr Z operator*(const Z &rhs) const { return static_cast<ull>(v) * rhs.v % Mod; }
inline constexpr Z inv() const;
inline constexpr Z operator/(const Z &rhs) const { return *this * rhs.inv(); }
constexpr operator uint() const { return v; }
};
inline constexpr Z &operator+=(Z &lhs, const Z &rhs) { return lhs = lhs + rhs; }
inline constexpr Z &operator-=(Z &lhs, const Z &rhs) { return lhs = lhs - rhs; }
inline constexpr Z &operator*=(Z &lhs, const Z &rhs) { return lhs = lhs * rhs; }
inline constexpr Z &operator/=(Z &lhs, const Z &rhs) { return lhs = lhs / rhs; }
inline constexpr Z pow(Z base, uint exp) {
Z res = 1;
for (; exp; base *= base, exp >>= 1)
if (exp & 1)
res *= base;
return res;
}
inline constexpr Z Z::inv() const { return pow(*this, Mod - 2); }
const int N = 30, M = 500, W = 153005;
static uniform_int_distribution<> uid0(0, (int) Mod), uid1(1, (int) Mod);
struct Trunc {
Z a, b;
Trunc() {}
Trunc(Z a, Z b) : a(a), b(b) {}
Trunc operator+(const Trunc &rhs) const { return Trunc(a + rhs.a, b + rhs.b); }
Trunc operator-(const Trunc &rhs) const { return Trunc(a - rhs.a, b - rhs.b); }
Trunc operator-() const { return Trunc(-a, -b); }
Trunc operator*(const Trunc &rhs) const {
return Trunc(a * rhs.a, Z((static_cast<ull>(b.v) * rhs.a.v + static_cast<ull>(a.v) * rhs.b.v) % Mod));
}
int deg() const {
if (a.v) return 0;
if (b.v) return 1;
return 2;
}
Trunc shift(int d) const {
if (d == 0) return *this;
return Trunc(0, a);
}
Trunc inv() const {
Trunc nv = Trunc();
nv.a = a.inv();
nv.b = -b * nv.a * nv.a;
return nv;
}
template<class URNG>
static Trunc rand(URNG &g) {
return Trunc({Z(uid1(g)), Z(uid0(g))});
}
};
inline Trunc &operator+=(Trunc &lhs, const Trunc &rhs) { return lhs = lhs + rhs; }
inline Trunc &operator-=(Trunc &lhs, const Trunc &rhs) { return lhs = lhs - rhs; }
inline Trunc &operator*=(Trunc &lhs, const Trunc &rhs) { return lhs = lhs * rhs; }
int n, m;
int u[M], v[M], w[M];
int edc[W], phi[W];
int f[N];
int find(int x) { return f[x] == x ? x : f[x] = find(f[x]); }
int tries;
const int LIMIT = 30;
int act;
namespace Kirkhoff {
int adj[N][N];
Trunc mat[N][N];
// works when #SpanningTrees % p != 0
vector<Trunc> BM(const vector<Trunc> &a) {
vector<Trunc> rec = {Trunc({Z(1), Z(0)})}, crec = {Trunc({Z(1), Z(0)})};
int l = 0;
for (int r = 1; r <= a.size(); ++r) {
Trunc v = Trunc();
for (int i = 0; i < rec.size(); ++i) v += rec[i] * a[r - 1 - i];
crec.insert(crec.begin(), Trunc());
if (v.deg() < 2) {
assert(v.deg() == 0);
vector<Trunc> t = rec;
if (crec.size() > t.size()) t.resize(crec.size());
for (int i = 0; i < crec.size(); ++i)
t[i] -= v * crec[i];
if (l * 2 <= r - 1) {
crec = rec;
Trunc nv = v.inv();
for (int i = 0; i < crec.size(); ++i)
crec[i] *= nv;
l = r - l;
}
swap(rec, t);
}
}
return rec;
}
Trunc diag[N], row[N], col[N];
int si[N * N], sj[N * N];
Trunc sw[N * N];
Trunc sparseDet(int n) {
++act;
while (true) {
++tries;
Trunc val = Trunc({Z(1), Z(0)});
for (int i = 0; i < n; ++i) {
diag[i] = Trunc::rand(rng);
val *= diag[i];
row[i] = Trunc::rand(rng);
col[i] = Trunc::rand(rng);
}
int tot = 0;
for (int i = 0; i < n; ++i)
for (int j = 0; j < n; ++j)
if (mat[i][j].deg() == 0) {
si[tot] = i;
sj[tot] = j;
sw[tot] = mat[i][j] * diag[i];
++tot;
}
vector<Trunc> vec;
for (int i = 0; i <= n * 2; ++i) {
static Trunc tmp[N];
fill(tmp, tmp + n, Trunc());
for (int j = 0; j < tot; ++j)
tmp[sj[j]] += row[si[j]] * sw[j];
vec.push_back(inner_product(tmp, tmp + n, col, Trunc()));
//cerr << vec.back().a << ' ' << vec.back().b << " | ";
copy(tmp, tmp + n, row);
}
//cerr << '\n';
auto rec = BM(vec);
//cerr << rec.size() << '\n';
if (rec.size() == n + 1) {
Trunc eigen = rec.back();
if (n & 1) eigen = -eigen;
return eigen * val.inv();
}
}
}
Trunc det(int n) {
Trunc ret = Trunc({Z(1), Z(0)});
for (int i = 0; i < n; ++i) {
int lowest = mat[i][i].deg(), pref = i;
for (int j = i + 1; j < n; ++j) {
if (lowest > mat[i][j].deg()) {
lowest = mat[i][j].deg();
pref = j;
}
}
if (pref != i) {
for (int j = i; j < n; ++j)
swap(mat[i][j], mat[pref][j]);
ret = -ret;
}
if (lowest + ret.deg() >= 2) return Trunc();
ret *= mat[i][i];
Trunc nv = Trunc();
if (lowest == 0) {
nv = mat[i][i].inv();
} else
nv.a = mat[i][i].b.inv();
for (int j = i; j < n; ++j)
mat[i][j] *= nv;
for (int j = i + 1; j < n; ++j)
for (int k = n - 1; k >= i; --k)
mat[j][k] -= (mat[i][k] * mat[j][i]).shift(mat[j][i].deg() - lowest);
}
return ret;
}
Z solve() {
for (int i = 0; i < n; ++i)
fill(mat[i], mat[i] + n, Trunc());
int cnt = 0;
for (int i = 0; i < n; ++i)
for (int j = 0; j < n; ++j)
if (adj[i][j]) {
Trunc e = Trunc({Z(1), Z(adj[i][j])});
mat[i][i] += e;
mat[j][j] += e;
mat[i][j] -= e;
mat[j][i] -= e;
++cnt;
}
Z ret = (cnt >= LIMIT ? det(n - 1) : sparseDet(n - 1)).b;
return ret;
}
}
unordered_map<bitset<M>, Z> memo;
int main() {
#ifdef ELEGIA
freopen("test.in", "r", stdin);
int nol_cl = clock();
#endif
ios::sync_with_stdio(false);
cin.tie(nullptr);
cin >> n >> m;
for (int i = 0; i < m; ++i) {
cin >> u[i] >> v[i] >> w[i];
--u[i];
--v[i];
++edc[w[i]];
}
iota(phi, phi + W, 0);
Z ans = 0;
int cnt = 0;
for (int i = 1; i < W; ++i) {
for (int j = i + i; j < W; j += i) {
edc[i] += edc[j];
phi[j] -= phi[i];
}
if (edc[i] < n - 1) continue;
iota(f, f + n, 0);
memset(Kirkhoff::adj, 0, sizeof(Kirkhoff::adj));
int con = n;
static bitset<M> edv;
edv.reset();
for (int j = 0; j < m; ++j)
if (w[j] % i == 0) {
edv.set(j);
Kirkhoff::adj[u[j]][v[j]] = w[j];
int x = find(u[j]), y = find(v[j]);
if (x != y) {
--con;
f[y] = x;
}
}
if (con != 1) continue;
auto it = memo.find(edv);
if (it != memo.end()) {
ans += it->second * Z(phi[i]);
continue;
}
++cnt;
Z th = Kirkhoff::solve();
ans += th * Z(phi[i]);
memo.insert(make_pair(edv, th));
}
cerr << "total dets: " << cnt << '\n';
cerr << "average attempts: " << (double)tries / act << '\n';
cout << ans << '\n';
#ifdef ELEGIA
LOG("Time: %dms\n", int ((clock()
-nol_cl) / (double)CLOCKS_PER_SEC * 1000));
#endif
return 0;
}
詳細信息
Pretests
Final Tests
Test #1:
score: 10
Accepted
time: 3ms
memory: 5000kb
input:
5 10 1 2 113400 1 3 131040 1 4 131040 1 5 126000 2 3 131040 2 4 90720 2 5 138600 3 4 110880 3 5 110880 4 5 95760
output:
549298858
result:
ok 1 number(s): "549298858"
Test #2:
score: 10
Accepted
time: 3ms
memory: 4852kb
input:
6 15 1 2 110880 1 3 141120 1 4 141120 1 5 131040 1 6 151200 2 3 137280 2 4 105840 2 5 138600 2 6 150480 3 4 138600 3 5 131040 3 6 137280 4 5 85680 4 6 151200 5 6 131040
output:
627752274
result:
ok 1 number(s): "627752274"
Test #3:
score: 10
Accepted
time: 3ms
memory: 4904kb
input:
25 24 1 2 147840 1 3 98280 2 4 120960 3 5 128520 5 6 128520 6 7 143640 1 8 138600 7 9 131040 3 10 147840 10 11 120120 5 12 120120 4 13 131040 8 14 151200 13 15 151200 5 16 110880 11 17 120960 6 18 151200 6 19 147840 5 20 147840 1 21 120960 14 22 110880 13 23 120120 18 24 98280 1 25 131040
output:
623404094
result:
ok 1 number(s): "623404094"
Test #4:
score: 10
Accepted
time: 3ms
memory: 4840kb
input:
28 28 1 2 128520 2 3 98280 1 4 138600 4 5 98280 2 6 98280 1 7 131040 3 8 138600 2 9 147840 6 10 120120 1 11 120960 7 12 138600 6 13 147840 3 14 120960 6 15 120960 9 16 120120 4 17 143640 3 18 128520 15 19 147840 9 20 120120 6 21 120960 20 22 147840 10 23 131040 5 24 138600 7 25 143640 5 26 120960 4 ...
output:
640377458
result:
ok 1 number(s): "640377458"
Test #5:
score: 10
Accepted
time: 0ms
memory: 4704kb
input:
30 30 1 2 110880 1 3 120960 3 4 131040 3 5 120120 3 6 138600 5 7 98280 3 8 120960 5 9 128520 1 10 128520 2 11 138600 5 12 98280 10 13 98280 11 14 143640 3 15 120960 10 16 98280 16 17 138600 5 18 138600 13 19 147840 18 20 120960 13 21 131040 15 22 151200 22 23 131040 2 24 128520 6 25 120960 20 26 138...
output:
309797364
result:
ok 1 number(s): "309797364"
Test #6:
score: 10
Accepted
time: 3ms
memory: 4796kb
input:
25 25 1 2 131040 2 3 120120 2 4 98280 3 5 110880 5 6 120120 4 7 120960 1 8 128520 4 9 110880 3 10 147840 7 11 120960 4 12 120960 2 13 138600 8 14 120960 1 15 128520 8 16 131040 10 17 110880 14 18 98280 9 19 131040 7 20 147840 8 21 138600 14 22 138600 5 23 151200 7 24 131040 13 25 143640 12 1 143640
output:
302382070
result:
ok 1 number(s): "302382070"
Test #7:
score: 10
Accepted
time: 3ms
memory: 4828kb
input:
28 376 1 2 152501 1 3 152501 1 4 152501 1 5 152501 1 6 152501 1 7 152501 1 8 152501 1 9 152501 1 10 152501 1 11 152501 1 12 152501 1 13 152501 1 14 152501 1 15 152501 1 16 152501 1 17 152501 1 18 152501 1 19 152501 1 20 152501 1 21 152501 1 22 152501 1 23 152501 1 24 152501 1 25 152501 1 26 152501 1...
output:
493255263
result:
ok 1 number(s): "493255263"
Test #8:
score: 10
Accepted
time: 3ms
memory: 4792kb
input:
30 431 1 2 152501 1 3 152501 1 4 152501 1 5 152501 1 6 152501 1 7 152501 1 8 152501 1 9 152501 1 10 152501 1 11 152501 1 12 152501 1 13 152501 1 14 152501 1 15 152501 1 16 152501 1 17 152501 1 18 152501 1 19 152501 1 20 152501 1 21 152501 1 22 152501 1 23 152501 1 24 152501 1 25 152501 1 26 152501 1...
output:
441996120
result:
ok 1 number(s): "441996120"
Test #9:
score: 10
Accepted
time: 3ms
memory: 4700kb
input:
28 372 1 2 152501 1 3 152501 1 4 152501 1 5 152501 1 6 152501 1 7 152501 1 8 152501 1 9 152501 1 10 152501 1 11 152501 1 12 152501 1 13 152501 1 14 152501 1 15 152501 1 16 152501 1 17 152501 1 18 152501 1 19 152501 1 20 152501 1 21 152501 1 22 152501 1 23 152501 1 24 152501 1 25 152501 1 26 152501 1...
output:
179882346
result:
ok 1 number(s): "179882346"
Test #10:
score: 10
Accepted
time: 3ms
memory: 4804kb
input:
30 432 1 2 152501 1 3 152501 1 4 152501 1 5 152501 1 6 152501 1 7 152501 1 8 152501 1 9 152501 1 10 152501 1 11 152501 1 12 152501 1 13 152501 1 14 152501 1 15 152501 1 16 152501 1 17 152501 1 18 152501 1 19 152501 1 20 152501 1 21 152501 1 22 152501 1 23 152501 1 24 152501 1 25 152501 1 26 152501 1...
output:
45748263
result:
ok 1 number(s): "45748263"
Extra Test:
score: 0
Extra Test Passed