This documentation is automatically generated by online-judge-tools/verification-helper
#include "linalg/spmat_det.hpp"
#include "linalg/spmat_min_poly.hpp"
template <typename T>
T spmat_det(int N, vc<tuple<int, int, T>> dat) {
vc<T> c(N);
FOR(i, N) c[i] = RNG(1, T::get_mod());
T r = 1;
FOR(i, N) r *= c[i];
for (auto&& [i, j, x]: dat) x *= c[i];
vc<T> f = spmat_min_poly(N, dat);
T det = (len(f) == N + 1 ? f[0] : T(0));
if (N & 1) det *= -1;
det /= r;
return det;
}
#line 2 "seq/find_linear_rec.hpp"
template <typename mint>
vector<mint> find_linear_rec(vector<mint>& A) {
int N = len(A);
vc<mint> B = {1}, C = {1};
int l = 0, m = 1;
mint p = 1;
FOR(i, N) {
mint d = A[i];
FOR3(j, 1, l + 1) { d += C[j] * A[i - j]; }
if (d == 0) {
++m;
continue;
}
auto tmp = C;
mint q = d / p;
if (len(C) < len(B) + m) C.insert(C.end(), len(B) + m - len(C), 0);
FOR(j, len(B)) C[j + m] -= q * B[j];
if (l + l <= i) {
B = tmp;
l = i + 1 - l, m = 1;
p = d;
} else {
++m;
}
}
return C;
}
#line 2 "random/base.hpp"
u64 RNG_64() {
static uint64_t x_
= uint64_t(chrono::duration_cast<chrono::nanoseconds>(
chrono::high_resolution_clock::now().time_since_epoch())
.count())
* 10150724397891781847ULL;
x_ ^= x_ << 7;
return x_ ^= x_ >> 9;
}
u64 RNG(u64 lim) { return RNG_64() % lim; }
ll RNG(ll l, ll r) { return l + RNG_64() % (r - l); }
#line 3 "linalg/spmat_min_poly.hpp"
template <typename mint>
vc<mint> spmat_min_poly(int N, vc<tuple<int, int, mint>> dat) {
vc<mint> S(N + N + 10);
vc<mint> c(N);
vc<mint> v(N);
FOR(i, N) c[i] = RNG(0, mint::get_mod());
FOR(i, N) v[i] = RNG(0, mint::get_mod());
FOR(k, N + N + 10) {
FOR(i, N) S[k] += c[i] * v[i];
vc<mint> w(N);
for (auto&& [i, j, x]: dat) w[j] += x * v[i];
swap(v, w);
}
vc<mint> f = find_linear_rec(S);
reverse(all(f));
return f;
}
#line 2 "linalg/spmat_det.hpp"
template <typename T>
T spmat_det(int N, vc<tuple<int, int, T>> dat) {
vc<T> c(N);
FOR(i, N) c[i] = RNG(1, T::get_mod());
T r = 1;
FOR(i, N) r *= c[i];
for (auto&& [i, j, x]: dat) x *= c[i];
vc<T> f = spmat_min_poly(N, dat);
T det = (len(f) == N + 1 ? f[0] : T(0));
if (N & 1) det *= -1;
det /= r;
return det;
}