This documentation is automatically generated by online-judge-tools/verification-helper
#include "graph/count/count_labeled_bridgeless.hpp"
#include "graph/count/count_labeled_connected.hpp"
#include "poly/compositional_inverse.hpp"
#include "poly/fps_exp.hpp"
#include "poly/fps_pow.hpp"
// 橋のない連結グラフ
// https://oeis.org/A095983
// N=1: 1
// O(Nlog^2N)
// https://atcoder.jp/contests/ttpc2023/tasks/ttpc2023_p
template <typename mint>
vc<mint> count_labeled_bridgeless(int N) {
vc<mint> C = count_labeled_connected<mint>(N);
FOR(i, N + 1) C[i] *= fact_inv<mint>(i);
vc<mint> D(N + 1);
FOR(i, N + 1) D[i] = mint(i) * C[i];
vc<mint> E = fps_exp(D);
E.insert(E.begin(), mint(0));
E.pop_back();
// D(x)=B(E(x))
vc<mint> IE = compositional_inverse(E);
vc<mint> B = composition(D, IE);
vc<mint> A(N + 1);
FOR(i, 1, N + 1) A[i] = B[i] * inv<mint>(i);
FOR(i, 1, N + 1) A[i] *= fact<mint>(i);
return A;
}
// https://oeis.org/A095983
// N での値のみ, O(NlogN)
template <typename mint>
mint count_labeled_bridgeless_single(int N) {
if (N == 0) return 0;
vc<mint> C = count_labeled_connected<mint>(N);
FOR(i, N + 1) C[i] *= fact_inv<mint>(i);
vc<mint> D(N + 1);
FOR(i, N + 1) D[i] = mint(i) * C[i];
vc<mint> E = fps_exp(D);
E.insert(E.begin(), mint(0));
E.pop_back();
// D(x)=B(E(x))
// [x^N]B(x) を求めたい
// Lagrange Inversion
// N[x^N]D(IE(x))=[x^{-1}]D'(x)E(x)^{-N}
// =[x^{N-1}]D'(x)(E(x)/x)^{-N}
E.erase(E.begin());
E = fps_pow_1<mint>(E, -N);
D = differentiate(D);
mint ANS = 0;
FOR(i, N) ANS += D[i] * E[N - 1 - i];
ANS *= inv<mint>(N);
// [x^N]B(x) が出た
ANS *= inv<mint>(N);
ANS *= fact<mint>(N);
return ANS;
}
#line 1 "graph/count/count_labeled_undirected.hpp"
// https://oeis.org/A006125
template <typename mint>
vc<mint> count_labeled_undirected(int N) {
vc<mint> F(N + 1);
mint pow2 = 1;
F[0] = 1;
FOR(i, 1, N + 1) F[i] = F[i - 1] * pow2, pow2 += pow2;
return F;
}
#line 2 "poly/fps_log.hpp"
#line 2 "poly/count_terms.hpp"
template<typename mint>
int count_terms(const vc<mint>& f){
int t = 0;
FOR(i, len(f)) if(f[i] != mint(0)) ++t;
return t;
}
#line 2 "mod/modint_common.hpp"
struct has_mod_impl {
template <class T>
static auto check(T &&x) -> decltype(x.get_mod(), std::true_type{});
template <class T>
static auto check(...) -> std::false_type;
};
template <class T>
class has_mod : public decltype(has_mod_impl::check<T>(std::declval<T>())) {};
template <typename mint>
mint inv(int n) {
static const int mod = mint::get_mod();
static vector<mint> dat = {0, 1};
assert(0 <= n);
if (n >= mod) n %= mod;
while (len(dat) <= n) {
int k = len(dat);
int q = (mod + k - 1) / k;
dat.eb(dat[k * q - mod] * mint::raw(q));
}
return dat[n];
}
template <typename mint>
mint fact(int n) {
static const int mod = mint::get_mod();
assert(0 <= n && n < mod);
static vector<mint> dat = {1, 1};
while (len(dat) <= n) dat.eb(dat[len(dat) - 1] * mint::raw(len(dat)));
return dat[n];
}
template <typename mint>
mint fact_inv(int n) {
static vector<mint> dat = {1, 1};
if (n < 0) return mint(0);
while (len(dat) <= n) dat.eb(dat[len(dat) - 1] * inv<mint>(len(dat)));
return dat[n];
}
template <class mint, class... Ts>
mint fact_invs(Ts... xs) {
return (mint(1) * ... * fact_inv<mint>(xs));
}
template <typename mint, class Head, class... Tail>
mint multinomial(Head &&head, Tail &&... tail) {
return fact<mint>(head) * fact_invs<mint>(std::forward<Tail>(tail)...);
}
template <typename mint>
mint C_dense(int n, int k) {
assert(n >= 0);
if (k < 0 || n < k) return 0;
static vvc<mint> C;
static int H = 0, W = 0;
auto calc = [&](int i, int j) -> mint {
if (i == 0) return (j == 0 ? mint(1) : mint(0));
return C[i - 1][j] + (j ? C[i - 1][j - 1] : 0);
};
if (W <= k) {
FOR(i, H) {
C[i].resize(k + 1);
FOR(j, W, k + 1) { C[i][j] = calc(i, j); }
}
W = k + 1;
}
if (H <= n) {
C.resize(n + 1);
FOR(i, H, n + 1) {
C[i].resize(W);
FOR(j, W) { C[i][j] = calc(i, j); }
}
H = n + 1;
}
return C[n][k];
}
template <typename mint, bool large = false, bool dense = false>
mint C(ll n, ll k) {
assert(n >= 0);
if (k < 0 || n < k) return 0;
if constexpr (dense) return C_dense<mint>(n, k);
if constexpr (!large) return multinomial<mint>(n, k, n - k);
k = min(k, n - k);
mint x(1);
FOR(i, k) x *= mint(n - i);
return x * fact_inv<mint>(k);
}
template <typename mint, bool large = false>
mint C_inv(ll n, ll k) {
assert(n >= 0);
assert(0 <= k && k <= n);
if (!large) return fact_inv<mint>(n) * fact<mint>(k) * fact<mint>(n - k);
return mint(1) / C<mint, 1>(n, k);
}
// [x^d](1-x)^{-n}
template <typename mint, bool large = false, bool dense = false>
mint C_negative(ll n, ll d) {
assert(n >= 0);
if (d < 0) return mint(0);
if (n == 0) { return (d == 0 ? mint(1) : mint(0)); }
return C<mint, large, dense>(n + d - 1, d);
}
#line 3 "mod/modint.hpp"
template <int mod>
struct modint {
static constexpr u32 umod = u32(mod);
static_assert(umod < u32(1) << 31);
u32 val;
static modint raw(u32 v) {
modint x;
x.val = v;
return x;
}
constexpr modint() : val(0) {}
constexpr modint(u32 x) : val(x % umod) {}
constexpr modint(u64 x) : val(x % umod) {}
constexpr modint(u128 x) : val(x % umod) {}
constexpr modint(int x) : val((x %= mod) < 0 ? x + mod : x){};
constexpr modint(ll x) : val((x %= mod) < 0 ? x + mod : x){};
constexpr modint(i128 x) : val((x %= mod) < 0 ? x + mod : x){};
bool operator<(const modint &other) const { return val < other.val; }
modint &operator+=(const modint &p) {
if ((val += p.val) >= umod) val -= umod;
return *this;
}
modint &operator-=(const modint &p) {
if ((val += umod - p.val) >= umod) val -= umod;
return *this;
}
modint &operator*=(const modint &p) {
val = u64(val) * p.val % umod;
return *this;
}
modint &operator/=(const modint &p) {
*this *= p.inverse();
return *this;
}
modint operator-() const { return modint::raw(val ? mod - val : u32(0)); }
modint operator+(const modint &p) const { return modint(*this) += p; }
modint operator-(const modint &p) const { return modint(*this) -= p; }
modint operator*(const modint &p) const { return modint(*this) *= p; }
modint operator/(const modint &p) const { return modint(*this) /= p; }
bool operator==(const modint &p) const { return val == p.val; }
bool operator!=(const modint &p) const { return val != p.val; }
modint inverse() const {
int a = val, b = mod, u = 1, v = 0, t;
while (b > 0) {
t = a / b;
swap(a -= t * b, b), swap(u -= t * v, v);
}
return modint(u);
}
modint pow(ll n) const {
if (n < 0) return inverse().pow(-n);
assert(n >= 0);
modint ret(1), mul(val);
while (n > 0) {
if (n & 1) ret *= mul;
mul *= mul;
n >>= 1;
}
return ret;
}
static constexpr int get_mod() { return mod; }
// (n, r), r は 1 の 2^n 乗根
static constexpr pair<int, int> ntt_info() {
if (mod == 120586241) return {20, 74066978};
if (mod == 167772161) return {25, 17};
if (mod == 469762049) return {26, 30};
if (mod == 754974721) return {24, 362};
if (mod == 880803841) return {23, 211};
if (mod == 943718401) return {22, 663003469};
if (mod == 998244353) return {23, 31};
if (mod == 1004535809) return {21, 582313106};
if (mod == 1012924417) return {21, 368093570};
return {-1, -1};
}
static constexpr bool can_ntt() { return ntt_info().fi != -1; }
};
#ifdef FASTIO
template <int mod>
void rd(modint<mod> &x) {
fastio::rd(x.val);
x.val %= mod;
// assert(0 <= x.val && x.val < mod);
}
template <int mod>
void wt(modint<mod> x) {
fastio::wt(x.val);
}
#endif
using modint107 = modint<1000000007>;
using modint998 = modint<998244353>;
#line 2 "mod/mod_inv.hpp"
// long でも大丈夫
// (val * x - 1) が mod の倍数になるようにする
// 特に mod=0 なら x=0 が満たす
ll mod_inv(ll val, ll mod) {
if (mod == 0) return 0;
mod = abs(mod);
val %= mod;
if (val < 0) val += mod;
ll a = val, b = mod, u = 1, v = 0, t;
while (b > 0) {
t = a / b;
swap(a -= t * b, b), swap(u -= t * v, v);
}
if (u < 0) u += mod;
return u;
}
#line 2 "mod/crt3.hpp"
constexpr u32 mod_pow_constexpr(u64 a, u64 n, u32 mod) {
a %= mod;
u64 res = 1;
FOR(32) {
if (n & 1) res = res * a % mod;
a = a * a % mod, n /= 2;
}
return res;
}
template <typename T, u32 p0, u32 p1>
T CRT2(u64 a0, u64 a1) {
static_assert(p0 < p1);
static constexpr u64 x0_1 = mod_pow_constexpr(p0, p1 - 2, p1);
u64 c = (a1 - a0 + p1) * x0_1 % p1;
return a0 + c * p0;
}
template <typename T, u32 p0, u32 p1, u32 p2>
T CRT3(u64 a0, u64 a1, u64 a2) {
static_assert(p0 < p1 && p1 < p2);
static constexpr u64 x1 = mod_pow_constexpr(p0, p1 - 2, p1);
static constexpr u64 x2 = mod_pow_constexpr(u64(p0) * p1 % p2, p2 - 2, p2);
static constexpr u64 p01 = u64(p0) * p1;
u64 c = (a1 - a0 + p1) * x1 % p1;
u64 ans_1 = a0 + c * p0;
c = (a2 - ans_1 % p2 + p2) * x2 % p2;
return T(ans_1) + T(c) * T(p01);
}
template <typename T, u32 p0, u32 p1, u32 p2, u32 p3>
T CRT4(u64 a0, u64 a1, u64 a2, u64 a3) {
static_assert(p0 < p1 && p1 < p2 && p2 < p3);
static constexpr u64 x1 = mod_pow_constexpr(p0, p1 - 2, p1);
static constexpr u64 x2 = mod_pow_constexpr(u64(p0) * p1 % p2, p2 - 2, p2);
static constexpr u64 x3 = mod_pow_constexpr(u64(p0) * p1 % p3 * p2 % p3, p3 - 2, p3);
static constexpr u64 p01 = u64(p0) * p1;
u64 c = (a1 - a0 + p1) * x1 % p1;
u64 ans_1 = a0 + c * p0;
c = (a2 - ans_1 % p2 + p2) * x2 % p2;
u128 ans_2 = ans_1 + c * static_cast<u128>(p01);
c = (a3 - ans_2 % p3 + p3) * x3 % p3;
return T(ans_2) + T(c) * T(p01) * T(p2);
}
template <typename T, u32 p0, u32 p1, u32 p2, u32 p3, u32 p4>
T CRT5(u64 a0, u64 a1, u64 a2, u64 a3, u64 a4) {
static_assert(p0 < p1 && p1 < p2 && p2 < p3 && p3 < p4);
static constexpr u64 x1 = mod_pow_constexpr(p0, p1 - 2, p1);
static constexpr u64 x2 = mod_pow_constexpr(u64(p0) * p1 % p2, p2 - 2, p2);
static constexpr u64 x3 = mod_pow_constexpr(u64(p0) * p1 % p3 * p2 % p3, p3 - 2, p3);
static constexpr u64 x4 = mod_pow_constexpr(u64(p0) * p1 % p4 * p2 % p4 * p3 % p4, p4 - 2, p4);
static constexpr u64 p01 = u64(p0) * p1;
static constexpr u64 p23 = u64(p2) * p3;
u64 c = (a1 - a0 + p1) * x1 % p1;
u64 ans_1 = a0 + c * p0;
c = (a2 - ans_1 % p2 + p2) * x2 % p2;
u128 ans_2 = ans_1 + c * static_cast<u128>(p01);
c = static_cast<u64>(a3 - ans_2 % p3 + p3) * x3 % p3;
u128 ans_3 = ans_2 + static_cast<u128>(c * p2) * p01;
c = static_cast<u64>(a4 - ans_3 % p4 + p4) * x4 % p4;
return T(ans_3) + T(c) * T(p01) * T(p23);
}
#line 2 "poly/convolution_naive.hpp"
template <class T, typename enable_if<!has_mod<T>::value>::type* = nullptr>
vc<T> convolution_naive(const vc<T>& a, const vc<T>& b) {
int n = int(a.size()), m = int(b.size());
if (n > m) return convolution_naive<T>(b, a);
if (n == 0) return {};
vector<T> ans(n + m - 1);
FOR(i, n) FOR(j, m) ans[i + j] += a[i] * b[j];
return ans;
}
template <class T, typename enable_if<has_mod<T>::value>::type* = nullptr>
vc<T> convolution_naive(const vc<T>& a, const vc<T>& b) {
int n = int(a.size()), m = int(b.size());
if (n > m) return convolution_naive<T>(b, a);
if (n == 0) return {};
vc<T> ans(n + m - 1);
if (n <= 16 && (T::get_mod() < (1 << 30))) {
for (int k = 0; k < n + m - 1; ++k) {
int s = max(0, k - m + 1);
int t = min(n, k + 1);
u64 sm = 0;
for (int i = s; i < t; ++i) { sm += u64(a[i].val) * (b[k - i].val); }
ans[k] = sm;
}
} else {
for (int k = 0; k < n + m - 1; ++k) {
int s = max(0, k - m + 1);
int t = min(n, k + 1);
u128 sm = 0;
for (int i = s; i < t; ++i) { sm += u64(a[i].val) * (b[k - i].val); }
ans[k] = T::raw(sm % T::get_mod());
}
}
return ans;
}
#line 2 "poly/convolution_karatsuba.hpp"
// 任意の環でできる
template <typename T>
vc<T> convolution_karatsuba(const vc<T>& f, const vc<T>& g) {
const int thresh = 30;
if (min(len(f), len(g)) <= thresh) return convolution_naive(f, g);
int n = max(len(f), len(g));
int m = ceil(n, 2);
vc<T> f1, f2, g1, g2;
if (len(f) < m) f1 = f;
if (len(f) >= m) f1 = {f.begin(), f.begin() + m};
if (len(f) >= m) f2 = {f.begin() + m, f.end()};
if (len(g) < m) g1 = g;
if (len(g) >= m) g1 = {g.begin(), g.begin() + m};
if (len(g) >= m) g2 = {g.begin() + m, g.end()};
vc<T> a = convolution_karatsuba(f1, g1);
vc<T> b = convolution_karatsuba(f2, g2);
FOR(i, len(f2)) f1[i] += f2[i];
FOR(i, len(g2)) g1[i] += g2[i];
vc<T> c = convolution_karatsuba(f1, g1);
vc<T> F(len(f) + len(g) - 1);
assert(2 * m + len(b) <= len(F));
FOR(i, len(a)) F[i] += a[i], c[i] -= a[i];
FOR(i, len(b)) F[2 * m + i] += b[i], c[i] -= b[i];
if (c.back() == T(0)) c.pop_back();
FOR(i, len(c)) if (c[i] != T(0)) F[m + i] += c[i];
return F;
}
#line 2 "poly/ntt.hpp"
template <class mint>
void ntt(vector<mint>& a, bool inverse) {
assert(mint::can_ntt());
const int rank2 = mint::ntt_info().fi;
const int mod = mint::get_mod();
static array<mint, 30> root, iroot;
static array<mint, 30> rate2, irate2;
static array<mint, 30> rate3, irate3;
assert(rank2 != -1 && len(a) <= (1 << max(0, rank2)));
static bool prepared = 0;
if (!prepared) {
prepared = 1;
root[rank2] = mint::ntt_info().se;
iroot[rank2] = mint(1) / root[rank2];
FOR_R(i, rank2) {
root[i] = root[i + 1] * root[i + 1];
iroot[i] = iroot[i + 1] * iroot[i + 1];
}
mint prod = 1, iprod = 1;
for (int i = 0; i <= rank2 - 2; i++) {
rate2[i] = root[i + 2] * prod;
irate2[i] = iroot[i + 2] * iprod;
prod *= iroot[i + 2];
iprod *= root[i + 2];
}
prod = 1, iprod = 1;
for (int i = 0; i <= rank2 - 3; i++) {
rate3[i] = root[i + 3] * prod;
irate3[i] = iroot[i + 3] * iprod;
prod *= iroot[i + 3];
iprod *= root[i + 3];
}
}
int n = int(a.size());
int h = topbit(n);
assert(n == 1 << h);
if (!inverse) {
int len = 0;
while (len < h) {
if (h - len == 1) {
int p = 1 << (h - len - 1);
mint rot = 1;
FOR(s, 1 << len) {
int offset = s << (h - len);
FOR(i, p) {
auto l = a[i + offset];
auto r = a[i + offset + p] * rot;
a[i + offset] = l + r;
a[i + offset + p] = l - r;
}
rot *= rate2[topbit(~s & -~s)];
}
len++;
} else {
int p = 1 << (h - len - 2);
mint rot = 1, imag = root[2];
for (int s = 0; s < (1 << len); s++) {
mint rot2 = rot * rot;
mint rot3 = rot2 * rot;
int offset = s << (h - len);
for (int i = 0; i < p; i++) {
u64 mod2 = u64(mod) * mod;
u64 a0 = a[i + offset].val;
u64 a1 = u64(a[i + offset + p].val) * rot.val;
u64 a2 = u64(a[i + offset + 2 * p].val) * rot2.val;
u64 a3 = u64(a[i + offset + 3 * p].val) * rot3.val;
u64 a1na3imag = (a1 + mod2 - a3) % mod * imag.val;
u64 na2 = mod2 - a2;
a[i + offset] = a0 + a2 + a1 + a3;
a[i + offset + 1 * p] = a0 + a2 + (2 * mod2 - (a1 + a3));
a[i + offset + 2 * p] = a0 + na2 + a1na3imag;
a[i + offset + 3 * p] = a0 + na2 + (mod2 - a1na3imag);
}
rot *= rate3[topbit(~s & -~s)];
}
len += 2;
}
}
} else {
mint coef = mint(1) / mint(len(a));
FOR(i, len(a)) a[i] *= coef;
int len = h;
while (len) {
if (len == 1) {
int p = 1 << (h - len);
mint irot = 1;
FOR(s, 1 << (len - 1)) {
int offset = s << (h - len + 1);
FOR(i, p) {
u64 l = a[i + offset].val;
u64 r = a[i + offset + p].val;
a[i + offset] = l + r;
a[i + offset + p] = (mod + l - r) * irot.val;
}
irot *= irate2[topbit(~s & -~s)];
}
len--;
} else {
int p = 1 << (h - len);
mint irot = 1, iimag = iroot[2];
FOR(s, (1 << (len - 2))) {
mint irot2 = irot * irot;
mint irot3 = irot2 * irot;
int offset = s << (h - len + 2);
for (int i = 0; i < p; i++) {
u64 a0 = a[i + offset + 0 * p].val;
u64 a1 = a[i + offset + 1 * p].val;
u64 a2 = a[i + offset + 2 * p].val;
u64 a3 = a[i + offset + 3 * p].val;
u64 x = (mod + a2 - a3) * iimag.val % mod;
a[i + offset] = a0 + a1 + a2 + a3;
a[i + offset + 1 * p] = (a0 + mod - a1 + x) * irot.val;
a[i + offset + 2 * p] = (a0 + a1 + 2 * mod - a2 - a3) * irot2.val;
a[i + offset + 3 * p] = (a0 + 2 * mod - a1 - x) * irot3.val;
}
irot *= irate3[topbit(~s & -~s)];
}
len -= 2;
}
}
}
}
#line 8 "poly/convolution.hpp"
template <class mint>
vector<mint> convolution_ntt(vector<mint> a, vector<mint> b) {
if (a.empty() || b.empty()) return {};
int n = int(a.size()), m = int(b.size());
int sz = 1;
while (sz < n + m - 1) sz *= 2;
// sz = 2^k のときの高速化。分割統治的なやつで損しまくるので。
if ((n + m - 3) <= sz / 2) {
auto a_last = a.back(), b_last = b.back();
a.pop_back(), b.pop_back();
auto c = convolution(a, b);
c.resize(n + m - 1);
c[n + m - 2] = a_last * b_last;
FOR(i, len(a)) c[i + len(b)] += a[i] * b_last;
FOR(i, len(b)) c[i + len(a)] += b[i] * a_last;
return c;
}
a.resize(sz), b.resize(sz);
bool same = a == b;
ntt(a, 0);
if (same) {
b = a;
} else {
ntt(b, 0);
}
FOR(i, sz) a[i] *= b[i];
ntt(a, 1);
a.resize(n + m - 1);
return a;
}
template <typename mint>
vector<mint> convolution_garner(const vector<mint>& a, const vector<mint>& b) {
int n = len(a), m = len(b);
if (!n || !m) return {};
static constexpr int p0 = 167772161;
static constexpr int p1 = 469762049;
static constexpr int p2 = 754974721;
using mint0 = modint<p0>;
using mint1 = modint<p1>;
using mint2 = modint<p2>;
vc<mint0> a0(n), b0(m);
vc<mint1> a1(n), b1(m);
vc<mint2> a2(n), b2(m);
FOR(i, n) a0[i] = a[i].val, a1[i] = a[i].val, a2[i] = a[i].val;
FOR(i, m) b0[i] = b[i].val, b1[i] = b[i].val, b2[i] = b[i].val;
auto c0 = convolution_ntt<mint0>(a0, b0);
auto c1 = convolution_ntt<mint1>(a1, b1);
auto c2 = convolution_ntt<mint2>(a2, b2);
vc<mint> c(len(c0));
FOR(i, n + m - 1) { c[i] = CRT3<mint, p0, p1, p2>(c0[i].val, c1[i].val, c2[i].val); }
return c;
}
vector<ll> convolution(vector<ll> a, vector<ll> b) {
int n = len(a), m = len(b);
if (!n || !m) return {};
if (min(n, m) <= 2500) return convolution_naive(a, b);
ll mi_a = MIN(a), mi_b = MIN(b);
for (auto& x: a) x -= mi_a;
for (auto& x: b) x -= mi_b;
assert(MAX(a) * MAX(b) <= 1e18);
auto Ac = cumsum<ll>(a), Bc = cumsum<ll>(b);
vi res(n + m - 1);
for (int k = 0; k < n + m - 1; ++k) {
int s = max(0, k - m + 1);
int t = min(n, k + 1);
res[k] += (t - s) * mi_a * mi_b;
res[k] += mi_a * (Bc[k - s + 1] - Bc[k - t + 1]);
res[k] += mi_b * (Ac[t] - Ac[s]);
}
static constexpr u32 MOD1 = 1004535809;
static constexpr u32 MOD2 = 1012924417;
using mint1 = modint<MOD1>;
using mint2 = modint<MOD2>;
vc<mint1> a1(n), b1(m);
vc<mint2> a2(n), b2(m);
FOR(i, n) a1[i] = a[i], a2[i] = a[i];
FOR(i, m) b1[i] = b[i], b2[i] = b[i];
auto c1 = convolution_ntt<mint1>(a1, b1);
auto c2 = convolution_ntt<mint2>(a2, b2);
FOR(i, n + m - 1) { res[i] += CRT2<u64, MOD1, MOD2>(c1[i].val, c2[i].val); }
return res;
}
template <typename mint>
vc<mint> convolution(const vc<mint>& a, const vc<mint>& b) {
int n = len(a), m = len(b);
if (!n || !m) return {};
if (mint::can_ntt()) {
if (min(n, m) <= 50) return convolution_karatsuba<mint>(a, b);
return convolution_ntt(a, b);
}
if (min(n, m) <= 200) return convolution_karatsuba<mint>(a, b);
return convolution_garner(a, b);
}
#line 4 "poly/fps_inv.hpp"
template <typename mint>
vc<mint> fps_inv_sparse(const vc<mint>& f) {
int N = len(f);
vc<pair<int, mint>> dat;
FOR(i, 1, N) if (f[i] != mint(0)) dat.eb(i, f[i]);
vc<mint> g(N);
mint g0 = mint(1) / f[0];
g[0] = g0;
FOR(n, 1, N) {
mint rhs = 0;
for (auto&& [k, fk]: dat) {
if (k > n) break;
rhs -= fk * g[n - k];
}
g[n] = rhs * g0;
}
return g;
}
template <typename mint>
vc<mint> fps_inv_dense_ntt(const vc<mint>& F) {
vc<mint> G = {mint(1) / F[0]};
ll N = len(F), n = 1;
G.reserve(N);
while (n < N) {
vc<mint> f(2 * n), g(2 * n);
FOR(i, min(N, 2 * n)) f[i] = F[i];
FOR(i, n) g[i] = G[i];
ntt(f, false), ntt(g, false);
FOR(i, 2 * n) f[i] *= g[i];
ntt(f, true);
FOR(i, n) f[i] = 0;
ntt(f, false);
FOR(i, 2 * n) f[i] *= g[i];
ntt(f, true);
FOR(i, n, min(N, 2 * n)) G.eb(-f[i]);
n *= 2;
}
return G;
}
template <typename mint>
vc<mint> fps_inv_dense(const vc<mint>& F) {
if (mint::can_ntt()) return fps_inv_dense_ntt(F);
const int N = len(F);
vc<mint> R = {mint(1) / F[0]};
vc<mint> p;
int m = 1;
while (m < N) {
p = convolution(R, R);
p.resize(m + m);
vc<mint> f = {F.begin(), F.begin() + min(m + m, N)};
p = convolution(p, f);
R.resize(m + m);
FOR(i, m + m) R[i] = R[i] + R[i] - p[i];
m += m;
}
R.resize(N);
return R;
}
template <typename mint>
vc<mint> fps_inv(const vc<mint>& f) {
assert(f[0] != mint(0));
int n = count_terms(f);
int t = (mint::can_ntt() ? 160 : 820);
return (n <= t ? fps_inv_sparse<mint>(f) : fps_inv_dense<mint>(f));
}
#line 5 "poly/fps_log.hpp"
template <typename mint>
vc<mint> fps_log_dense(const vc<mint>& f) {
assert(f[0] == mint(1));
ll N = len(f);
vc<mint> df = f;
FOR(i, N) df[i] *= mint(i);
df.erase(df.begin());
auto f_inv = fps_inv(f);
auto g = convolution(df, f_inv);
g.resize(N - 1);
g.insert(g.begin(), 0);
FOR(i, N) g[i] *= inv<mint>(i);
return g;
}
template <typename mint>
vc<mint> fps_log_sparse(const vc<mint>& f) {
int N = f.size();
vc<pair<int, mint>> dat;
FOR(i, 1, N) if (f[i] != mint(0)) dat.eb(i, f[i]);
vc<mint> F(N);
vc<mint> g(N - 1);
for (int n = 0; n < N - 1; ++n) {
mint rhs = mint(n + 1) * f[n + 1];
for (auto&& [i, fi]: dat) {
if (i > n) break;
rhs -= fi * g[n - i];
}
g[n] = rhs;
F[n + 1] = rhs * inv<mint>(n + 1);
}
return F;
}
template <typename mint>
vc<mint> fps_log(const vc<mint>& f) {
assert(f[0] == mint(1));
int n = count_terms(f);
int t = (mint::can_ntt() ? 200 : 1200);
return (n <= t ? fps_log_sparse<mint>(f) : fps_log_dense<mint>(f));
}
#line 3 "graph/count/count_labeled_connected.hpp"
// https://oeis.org/A001187
template <typename mint>
vc<mint> count_labeled_connected(int N) {
vc<mint> F = count_labeled_undirected<mint>(N);
FOR(i, N + 1) F[i] *= fact_inv<mint>(i);
F = fps_log(F);
FOR(i, N + 1) F[i] *= fact<mint>(i);
return F;
}
#line 2 "poly/differentiate.hpp"
template <typename mint>
vc<mint> differentiate(const vc<mint>& f) {
if (len(f) <= 1) return {};
vc<mint> g(len(f) - 1);
FOR(i, len(g)) g[i] = f[i + 1] * mint(i + 1);
return g;
}
#line 2 "poly/composition.hpp"
#line 2 "poly/poly_taylor_shift.hpp"
#line 2 "nt/primetable.hpp"
template <typename T = int>
vc<T> primetable(int LIM) {
++LIM;
const int S = 32768;
static int done = 2;
static vc<T> primes = {2}, sieve(S + 1);
if (done < LIM) {
done = LIM;
primes = {2}, sieve.assign(S + 1, 0);
const int R = LIM / 2;
primes.reserve(int(LIM / log(LIM) * 1.1));
vc<pair<int, int>> cp;
for (int i = 3; i <= S; i += 2) {
if (!sieve[i]) {
cp.eb(i, i * i / 2);
for (int j = i * i; j <= S; j += 2 * i) sieve[j] = 1;
}
}
for (int L = 1; L <= R; L += S) {
array<bool, S> block{};
for (auto& [p, idx]: cp)
for (int i = idx; i < S + L; idx = (i += p)) block[i - L] = 1;
FOR(i, min(S, R - L)) if (!block[i]) primes.eb((L + i) * 2 + 1);
}
}
int k = LB(primes, LIM + 1);
return {primes.begin(), primes.begin() + k};
}
#line 3 "mod/powertable.hpp"
// a^0, ..., a^N
template <typename mint>
vc<mint> powertable_1(mint a, ll N) {
// table of a^i
vc<mint> f(N + 1, 1);
FOR(i, N) f[i + 1] = a * f[i];
return f;
}
// 0^e, ..., N^e
template <typename mint>
vc<mint> powertable_2(ll e, ll N) {
auto primes = primetable(N);
vc<mint> f(N + 1, 1);
f[0] = mint(0).pow(e);
for (auto&& p: primes) {
if (p > N) break;
mint xp = mint(p).pow(e);
ll pp = p;
while (pp <= N) {
ll i = pp;
while (i <= N) {
f[i] *= xp;
i += pp;
}
pp *= p;
}
}
return f;
}
#line 5 "poly/poly_taylor_shift.hpp"
// f(x) -> f(x+c)
template <typename mint>
vc<mint> poly_taylor_shift(vc<mint> f, mint c) {
if (c == mint(0)) return f;
ll N = len(f);
FOR(i, N) f[i] *= fact<mint>(i);
auto b = powertable_1<mint>(c, N);
FOR(i, N) b[i] *= fact_inv<mint>(i);
reverse(all(f));
f = convolution(f, b);
f.resize(N);
reverse(all(f));
FOR(i, N) f[i] *= fact_inv<mint>(i);
return f;
}
#line 2 "poly/transposed_ntt.hpp"
template <class mint>
void transposed_ntt(vector<mint>& a, bool inverse) {
assert(mint::can_ntt());
const int rank2 = mint::ntt_info().fi;
const int mod = mint::get_mod();
static array<mint, 30> root, iroot;
static array<mint, 30> rate2, irate2;
static array<mint, 30> rate3, irate3;
assert(rank2 != -1 && len(a) <= (1 << max(0, rank2)));
static bool prepared = 0;
if (!prepared) {
prepared = 1;
root[rank2] = mint::ntt_info().se;
iroot[rank2] = mint(1) / root[rank2];
FOR_R(i, rank2) {
root[i] = root[i + 1] * root[i + 1];
iroot[i] = iroot[i + 1] * iroot[i + 1];
}
mint prod = 1, iprod = 1;
for (int i = 0; i <= rank2 - 2; i++) {
rate2[i] = root[i + 2] * prod;
irate2[i] = iroot[i + 2] * iprod;
prod *= iroot[i + 2];
iprod *= root[i + 2];
}
prod = 1, iprod = 1;
for (int i = 0; i <= rank2 - 3; i++) {
rate3[i] = root[i + 3] * prod;
irate3[i] = iroot[i + 3] * iprod;
prod *= iroot[i + 3];
iprod *= root[i + 3];
}
}
int n = int(a.size());
int h = topbit(n);
assert(n == 1 << h);
if (!inverse) {
int len = h;
while (len > 0) {
if (len == 1) {
int p = 1 << (h - len);
mint rot = 1;
FOR(s, 1 << (len - 1)) {
int offset = s << (h - len + 1);
FOR(i, p) {
u64 l = a[i + offset].val;
u64 r = a[i + offset + p].val;
a[i + offset] = l + r;
a[i + offset + p] = (mod + l - r) * rot.val;
}
rot *= rate2[topbit(~s & -~s)];
}
len--;
} else {
int p = 1 << (h - len);
mint rot = 1, imag = root[2];
FOR(s, (1 << (len - 2))) {
int offset = s << (h - len + 2);
mint rot2 = rot * rot;
mint rot3 = rot2 * rot;
for (int i = 0; i < p; i++) {
u64 a0 = a[i + offset + 0 * p].val;
u64 a1 = a[i + offset + 1 * p].val;
u64 a2 = a[i + offset + 2 * p].val;
u64 a3 = a[i + offset + 3 * p].val;
u64 x = (mod + a2 - a3) * imag.val % mod;
a[i + offset] = a0 + a1 + a2 + a3;
a[i + offset + 1 * p] = (a0 + mod - a1 + x) * rot.val;
a[i + offset + 2 * p] = (a0 + a1 + 2 * mod - a2 - a3) * rot2.val;
a[i + offset + 3 * p] = (a0 + 2 * mod - a1 - x) * rot3.val;
}
rot *= rate3[topbit(~s & -~s)];
}
len -= 2;
}
}
} else {
mint coef = mint(1) / mint(len(a));
FOR(i, len(a)) a[i] *= coef;
int len = 0;
while (len < h) {
if (len == h - 1) {
int p = 1 << (h - len - 1);
mint irot = 1;
FOR(s, 1 << len) {
int offset = s << (h - len);
FOR(i, p) {
auto l = a[i + offset];
auto r = a[i + offset + p] * irot;
a[i + offset] = l + r;
a[i + offset + p] = l - r;
}
irot *= irate2[topbit(~s & -~s)];
}
len++;
} else {
int p = 1 << (h - len - 2);
mint irot = 1, iimag = iroot[2];
for (int s = 0; s < (1 << len); s++) {
mint irot2 = irot * irot;
mint irot3 = irot2 * irot;
int offset = s << (h - len);
for (int i = 0; i < p; i++) {
u64 mod2 = u64(mod) * mod;
u64 a0 = a[i + offset].val;
u64 a1 = u64(a[i + offset + p].val) * irot.val;
u64 a2 = u64(a[i + offset + 2 * p].val) * irot2.val;
u64 a3 = u64(a[i + offset + 3 * p].val) * irot3.val;
u64 a1na3imag = (a1 + mod2 - a3) % mod * iimag.val;
u64 na2 = mod2 - a2;
a[i + offset] = a0 + a2 + a1 + a3;
a[i + offset + 1 * p] = a0 + a2 + (2 * mod2 - (a1 + a3));
a[i + offset + 2 * p] = a0 + na2 + a1na3imag;
a[i + offset + 3 * p] = a0 + na2 + (mod2 - a1na3imag);
}
irot *= irate3[topbit(~s & -~s)];
}
len += 2;
}
}
}
}
#line 6 "poly/composition.hpp"
template <typename mint>
vc<mint> composition_old(vc<mint>& Q, vc<mint>& P) {
int n = len(P);
assert(len(P) == len(Q));
int k = 1;
while (k * k < n) ++k;
// compute powers of P
vv(mint, pow1, k + 1);
pow1[0] = {1};
pow1[1] = P;
FOR3(i, 2, k + 1) {
pow1[i] = convolution(pow1[i - 1], pow1[1]);
pow1[i].resize(n);
}
vv(mint, pow2, k + 1);
pow2[0] = {1};
pow2[1] = pow1[k];
FOR3(i, 2, k + 1) {
pow2[i] = convolution(pow2[i - 1], pow2[1]);
pow2[i].resize(n);
}
vc<mint> ANS(n);
FOR(i, k + 1) {
vc<mint> f(n);
FOR(j, k) {
if (k * i + j < len(Q)) {
mint coef = Q[k * i + j];
FOR(d, len(pow1[j])) f[d] += pow1[j][d] * coef;
}
}
f = convolution(f, pow2[i]);
f.resize(n);
FOR(d, n) ANS[d] += f[d];
}
return ANS;
}
// f(g(x)), O(Nlog^2N)
template <typename mint>
vc<mint> composition_0_ntt(vc<mint> f, vc<mint> g) {
assert(len(f) == len(g));
if (f.empty()) return {};
int n0 = len(f);
int n = 1;
while (n < len(f)) n *= 2;
f.resize(n), g.resize(n);
vc<mint> W(n);
{
// bit reverse order
vc<int> btr(n);
int log = topbit(n);
FOR(i, n) { btr[i] = (btr[i >> 1] >> 1) + ((i & 1) << (log - 1)); }
int t = mint::ntt_info().fi;
mint r = mint::ntt_info().se;
mint dw = r.inverse().pow((1 << t) / (2 * n));
mint w = 1;
for (auto& i: btr) { W[i] = w, w *= dw; }
}
auto rec = [&](auto& rec, int n, int k, vc<mint>& Q) -> vc<mint> {
if (n == 1) {
reverse(all(f));
transposed_ntt(f, 1);
mint c = mint(1) / mint(k);
for (auto& x: f) x *= c;
vc<mint> p(4 * k);
FOR(i, k) p[2 * i] = f[i];
return p;
}
auto doubling_y = [&](vc<mint>& A, int l, int r, bool t) -> void {
mint z = W[k / 2].inverse();
vc<mint> f(k);
if (!t) {
FOR(i, l, r) {
FOR(j, k) f[j] = A[2 * n * j + i];
ntt(f, 1);
mint r = 1;
FOR(j, 1, k) r *= z, f[j] *= r;
ntt(f, 0);
FOR(j, k) A[2 * n * (k + j) + i] = f[j];
}
} else {
FOR(i, l, r) {
FOR(j, k) f[j] = A[2 * n * (k + j) + i];
transposed_ntt(f, 0);
mint r = 1;
FOR(j, 1, k) r *= z, f[j] *= r;
transposed_ntt(f, 1);
FOR(j, k) A[2 * n * j + i] += f[j];
}
}
};
auto FFT_x = [&](vc<mint>& A, int l, int r, bool t) -> void {
vc<mint> f(2 * n);
if (!t) {
FOR(j, l, r) {
move(A.begin() + 2 * n * j, A.begin() + 2 * n * (j + 1), f.begin());
ntt(f, 0);
move(all(f), A.begin() + 2 * n * j);
}
} else {
FOR(j, l, r) {
move(A.begin() + 2 * n * j, A.begin() + 2 * n * (j + 1), f.begin());
transposed_ntt(f, 0);
move(all(f), A.begin() + 2 * n * j);
}
}
};
if (n <= k) doubling_y(Q, 1, n, 0), FFT_x(Q, 0, 2 * k, 0);
if (n > k) FFT_x(Q, 0, k, 0), doubling_y(Q, 0, 2 * n, 0);
FOR(i, 2 * n * k) Q[i] += 1;
FOR(i, 2 * n * k, 4 * n * k) Q[i] -= 1;
vc<mint> nxt_Q(4 * n * k);
vc<mint> F(2 * n), G(2 * n), f(n), g(n);
FOR(j, 2 * k) {
move(Q.begin() + 2 * n * j, Q.begin() + 2 * n * j + 2 * n, G.begin());
FOR(i, n) { g[i] = G[2 * i] * G[2 * i + 1]; }
ntt(g, 1);
move(g.begin(), g.begin() + n / 2, nxt_Q.begin() + n * j);
}
FOR(j, 4 * k) nxt_Q[n * j] = 0;
vc<mint> p = rec(rec, n / 2, k * 2, nxt_Q);
FOR_R(j, 2 * k) {
move(p.begin() + n * j, p.begin() + n * j + n / 2, f.begin());
move(Q.begin() + 2 * n * j, Q.begin() + 2 * n * j + 2 * n, G.begin());
fill(f.begin() + n / 2, f.end(), mint(0));
transposed_ntt(f, 1);
FOR(i, n) {
f[i] *= W[i];
F[2 * i] = G[2 * i + 1] * f[i], F[2 * i + 1] = -G[2 * i] * f[i];
}
move(F.begin(), F.end(), p.begin() + 2 * n * j);
}
if (n <= k) FFT_x(p, 0, 2 * k, 1), doubling_y(p, 0, n, 1);
if (n > k) doubling_y(p, 0, 2 * n, 1), FFT_x(p, 0, k, 1);
return p;
};
vc<mint> Q(4 * n);
FOR(i, n) Q[i] = -g[i];
vc<mint> p = rec(rec, n, 1, Q);
p.resize(n);
reverse(all(p));
p.resize(n0);
return p;
}
template <typename mint>
vc<mint> composition_0_garner(vc<mint> f, vc<mint> g) {
constexpr u32 ps[] = {167772161, 469762049, 754974721};
using mint0 = modint<ps[0]>;
using mint1 = modint<ps[1]>;
using mint2 = modint<ps[2]>;
auto rec = [&](auto& rec, int n, int k, vc<mint> Q) -> vc<mint> {
if (n == 1) {
vc<mint> p(2 * k);
reverse(all(f));
FOR(i, k) p[2 * i] = f[i];
return p;
}
vc<mint0> Q0(4 * n * k), R0(4 * n * k), p0(4 * n * k);
vc<mint1> Q1(4 * n * k), R1(4 * n * k), p1(4 * n * k);
vc<mint2> Q2(4 * n * k), R2(4 * n * k), p2(4 * n * k);
FOR(i, 2 * n * k) {
Q0[i] = Q[i].val, R0[i] = (i % 2 == 0 ? Q[i].val : (-Q[i]).val);
Q1[i] = Q[i].val, R1[i] = (i % 2 == 0 ? Q[i].val : (-Q[i]).val);
Q2[i] = Q[i].val, R2[i] = (i % 2 == 0 ? Q[i].val : (-Q[i]).val);
}
ntt(Q0, 0), ntt(Q1, 0), ntt(Q2, 0), ntt(R0, 0), ntt(R1, 0), ntt(R2, 0);
FOR(i, 4 * n * k) Q0[i] *= R0[i], Q1[i] *= R1[i], Q2[i] *= R2[i];
ntt(Q0, 1), ntt(Q1, 1), ntt(Q2, 1);
vc<mint> QQ(4 * n * k);
FOR(i, 4 * n * k) {
QQ[i] = CRT3<mint, ps[0], ps[1], ps[2]>(Q0[i].val, Q1[i].val, Q2[i].val);
}
FOR(i, 0, 2 * n * k, 2) { QQ[2 * n * k + i] += Q[i] + Q[i]; }
vc<mint> nxt_Q(2 * n * k);
FOR(j, 2 * k) FOR(i, n / 2) {
nxt_Q[n * j + i] = QQ[(2 * n) * j + (2 * i + 0)];
}
vc<mint> nxt_p = rec(rec, n / 2, k * 2, nxt_Q);
vc<mint> pq(4 * n * k);
FOR(j, 2 * k) FOR(i, n / 2) {
pq[(2 * n) * j + (2 * i + 1)] += nxt_p[n * j + i];
}
vc<mint> p(2 * n * k);
FOR(i, 2 * n * k) { p[i] += pq[2 * n * k + i]; }
FOR(i, 4 * n * k) {
p0[i] += pq[i].val, p1[i] += pq[i].val, p2[i] += pq[i].val;
}
transposed_ntt(p0, 1), transposed_ntt(p1, 1), transposed_ntt(p2, 1);
FOR(i, 4 * n * k) p0[i] *= R0[i], p1[i] *= R1[i], p2[i] *= R2[i];
transposed_ntt(p0, 0), transposed_ntt(p1, 0), transposed_ntt(p2, 0);
FOR(i, 2 * n * k) {
p[i] += CRT3<mint, ps[0], ps[1], ps[2]>(p0[i].val, p1[i].val, p2[i].val);
}
return p;
};
assert(len(f) == len(g));
int n = 1;
while (n < len(f)) n *= 2;
int out_len = len(f);
f.resize(n), g.resize(n);
int k = 1;
vc<mint> Q(2 * n);
FOR(i, n) Q[i] = -g[i];
vc<mint> p = rec(rec, n, k, Q);
vc<mint> output(n);
FOR(i, n) output[i] = p[i];
reverse(all(output));
output.resize(out_len);
return output;
}
template <typename mint>
vc<mint> composition(vc<mint> f, vc<mint> g) {
assert(len(f) == len(g));
if (f.empty()) return {};
// [x^0]g=0 に帰着しておく
if (g[0] != mint(0)) {
f = poly_taylor_shift<mint>(f, g[0]);
g[0] = 0;
}
if (mint::can_ntt()) { return composition_0_ntt(f, g); }
return composition_0_garner(f, g);
}
#line 2 "poly/fps_div.hpp"
#line 5 "poly/fps_div.hpp"
// f/g. f の長さで出力される.
template <typename mint, bool SPARSE = false>
vc<mint> fps_div(vc<mint> f, vc<mint> g) {
if (SPARSE || count_terms(g) < 200) return fps_div_sparse(f, g);
int n = len(f);
g.resize(n);
g = fps_inv<mint>(g);
f = convolution(f, g);
f.resize(n);
return f;
}
// f/g ただし g は sparse
template <typename mint>
vc<mint> fps_div_sparse(vc<mint> f, vc<mint>& g) {
if (g[0] != mint(1)) {
mint cf = g[0].inverse();
for (auto&& x: f) x *= cf;
for (auto&& x: g) x *= cf;
}
vc<pair<int, mint>> dat;
FOR(i, 1, len(g)) if (g[i] != mint(0)) dat.eb(i, -g[i]);
FOR(i, len(f)) {
for (auto&& [j, x]: dat) {
if (i >= j) f[i] += x * f[i - j];
}
}
return f;
}
#line 2 "poly/integrate.hpp"
// 不定積分:integrate(f)
// 定積分:integrate(f, L, R)
template <typename mint>
vc<mint> integrate(const vc<mint>& f) {
vc<mint> g(len(f) + 1);
FOR3(i, 1, len(g)) g[i] = f[i - 1] * inv<mint>(i);
return g;
}
// 不定積分:integrate(f)
// 定積分:integrate(f, L, R)
template <typename mint>
mint integrate(const vc<mint>& f, mint L, mint R) {
mint I = 0;
mint pow_L = 1, pow_R = 1;
FOR(i, len(f)) {
pow_L *= L, pow_R *= R;
I += inv<mint>(i + 1) * f[i] * (pow_R - pow_L);
}
return I;
}
#line 6 "poly/fps_exp.hpp"
template <typename mint>
vc<mint> fps_exp_sparse(vc<mint>& f) {
if (len(f) == 0) return {mint(1)};
assert(f[0] == 0);
int N = len(f);
// df を持たせる
vc<pair<int, mint>> dat;
FOR(i, 1, N) if (f[i] != mint(0)) dat.eb(i - 1, mint(i) * f[i]);
vc<mint> F(N);
F[0] = 1;
FOR(n, 1, N) {
mint rhs = 0;
for (auto&& [k, fk]: dat) {
if (k > n - 1) break;
rhs += fk * F[n - 1 - k];
}
F[n] = rhs * inv<mint>(n);
}
return F;
}
template <typename mint>
vc<mint> fps_exp_dense(vc<mint>& h) {
const int n = len(h);
assert(n > 0 && h[0] == mint(0));
if (mint::can_ntt()) {
vc<mint>& f = h;
vc<mint> b = {1, (1 < n ? f[1] : 0)};
vc<mint> c = {1}, z1, z2 = {1, 1};
while (len(b) < n) {
int m = len(b);
auto y = b;
y.resize(2 * m);
ntt(y, 0);
z1 = z2;
vc<mint> z(m);
FOR(i, m) z[i] = y[i] * z1[i];
ntt(z, 1);
FOR(i, m / 2) z[i] = 0;
ntt(z, 0);
FOR(i, m) z[i] *= -z1[i];
ntt(z, 1);
c.insert(c.end(), z.begin() + m / 2, z.end());
z2 = c;
z2.resize(2 * m);
ntt(z2, 0);
vc<mint> x(f.begin(), f.begin() + m);
FOR(i, len(x) - 1) x[i] = x[i + 1] * mint(i + 1);
x.back() = 0;
ntt(x, 0);
FOR(i, m) x[i] *= y[i];
ntt(x, 1);
FOR(i, m - 1) x[i] -= b[i + 1] * mint(i + 1);
x.resize(m + m);
FOR(i, m - 1) x[m + i] = x[i], x[i] = 0;
ntt(x, 0);
FOR(i, m + m) x[i] *= z2[i];
ntt(x, 1);
FOR_R(i, len(x) - 1) x[i + 1] = x[i] * inv<mint>(i + 1);
x[0] = 0;
FOR3(i, m, min(n, m + m)) x[i] += f[i];
FOR(i, m) x[i] = 0;
ntt(x, 0);
FOR(i, m + m) x[i] *= y[i];
ntt(x, 1);
b.insert(b.end(), x.begin() + m, x.end());
}
b.resize(n);
return b;
}
const int L = len(h);
assert(L > 0 && h[0] == mint(0));
int LOG = 0;
while (1 << LOG < L) ++LOG;
h.resize(1 << LOG);
auto dh = differentiate(h);
vc<mint> f = {1}, g = {1};
int m = 1;
vc<mint> p;
FOR(LOG) {
p = convolution(f, g);
p.resize(m);
p = convolution(p, g);
p.resize(m);
g.resize(m);
FOR(i, m) g[i] += g[i] - p[i];
p = {dh.begin(), dh.begin() + m - 1};
p = convolution(f, p);
p.resize(m + m - 1);
FOR(i, m + m - 1) p[i] = -p[i];
FOR(i, m - 1) p[i] += mint(i + 1) * f[i + 1];
p = convolution(p, g);
p.resize(m + m - 1);
FOR(i, m - 1) p[i] += dh[i];
p = integrate(p);
FOR(i, m + m) p[i] = h[i] - p[i];
p[0] += mint(1);
f = convolution(f, p);
f.resize(m + m);
m += m;
}
f.resize(L);
return f;
}
template <typename mint>
vc<mint> fps_exp(vc<mint>& f) {
int n = count_terms(f);
int t = (mint::can_ntt() ? 320 : 3000);
return (n <= t ? fps_exp_sparse<mint>(f) : fps_exp_dense<mint>(f));
}
#line 5 "poly/fps_pow.hpp"
// fps の k 乗を求める。k >= 0 の前提である。
// 定数項が 1 で、k が mint の場合には、fps_pow_1 を使うこと。
// ・dense な場合: log, exp を使う O(NlogN)
// ・sparse な場合: O(NK)
template <typename mint>
vc<mint> fps_pow(const vc<mint>& f, ll k) {
assert(0 <= k);
int n = len(f);
if (k == 0) {
vc<mint> g(n);
g[0] = mint(1);
return g;
}
int d = n;
FOR_R(i, n) if (f[i] != 0) d = i;
// d * k >= n
if (d >= ceil<ll>(n, k)) {
vc<mint> g(n);
return g;
}
ll off = d * k;
mint c = f[d];
mint c_inv = mint(1) / mint(c);
vc<mint> g(n - off);
FOR(i, n - off) g[i] = f[d + i] * c_inv;
g = fps_pow_1(g, mint(k));
vc<mint> h(n);
c = c.pow(k);
FOR(i, len(g)) h[off + i] = g[i] * c;
return h;
}
template <typename mint>
vc<mint> fps_pow_1_sparse(const vc<mint>& f, mint K) {
int N = len(f);
assert(N == 0 || f[0] == mint(1));
vc<pair<int, mint>> dat;
FOR(i, 1, N) if (f[i] != mint(0)) dat.eb(i, f[i]);
vc<mint> g(N);
g[0] = 1;
FOR(n, N - 1) {
mint& x = g[n + 1];
for (auto&& [d, cf]: dat) {
if (d > n + 1) break;
mint t = cf * g[n - d + 1];
x += t * (K * mint(d) - mint(n - d + 1));
}
x *= inv<mint>(n + 1);
}
return g;
}
template <typename mint>
vc<mint> fps_pow_1_dense(const vc<mint>& f, mint K) {
assert(f[0] == mint(1));
auto log_f = fps_log(f);
FOR(i, len(f)) log_f[i] *= K;
return fps_exp_dense(log_f);
}
template <typename mint>
vc<mint> fps_pow_1(const vc<mint>& f, mint K) {
int n = count_terms(f);
int t = (mint::can_ntt() ? 100 : 1300);
return (n <= t ? fps_pow_1_sparse(f, K) : fps_pow_1_dense(f, K));
}
// f^e, sparse, O(NMK)
template <typename mint>
vvc<mint> fps_pow_1_sparse_2d(vvc<mint> f, mint n) {
assert(f[0][0] == mint(1));
int N = len(f), M = len(f[0]);
vv(mint, dp, N, M);
dp[0] = fps_pow_1_sparse<mint>(f[0], n);
vc<tuple<int, int, mint>> dat;
FOR(i, N) FOR(j, M) {
if ((i > 0 || j > 0) && f[i][j] != mint(0)) dat.eb(i, j, f[i][j]);
}
FOR(i, 1, N) {
FOR(j, M) {
// F = f^n, f dF = n df F
// [x^{i-1}y^j]
mint lhs = 0, rhs = 0;
for (auto&& [a, b, c]: dat) {
if (a < i && b <= j) lhs += dp[i - a][j - b] * mint(i - a);
if (a <= i && b <= j) rhs += dp[i - a][j - b] * c * mint(a);
}
dp[i][j] = (n * rhs - lhs) * inv<mint>(i);
}
}
return dp;
}
#line 2 "poly/power_projection.hpp"
#line 4 "poly/power_projection.hpp"
template <typename mint>
vc<mint> power_projection_0_ntt(vc<mint> wt, vc<mint> f, int m) {
assert(len(f) == len(wt) && f[0] == mint(0));
int n = 1;
while (n < len(f)) n *= 2;
for (auto& x: f) x = -x;
f.resize(n), wt.resize(n);
reverse(all(wt));
vc<mint>&P = wt, &Q = f;
P.resize(4 * n), Q.resize(4 * n);
vc<mint> W(n);
{
// bit reverse order
vc<int> btr(n);
int log = topbit(n);
FOR(i, n) { btr[i] = (btr[i >> 1] >> 1) + ((i & 1) << (log - 1)); }
int t = mint::ntt_info().fi;
mint r = mint::ntt_info().se;
mint dw = r.inverse().pow((1 << t) / (2 * n));
mint w = 1;
for (auto& i: btr) { W[i] = w, w *= dw; }
}
int k = 1;
while (n > 1) {
/*
FFT step
04.. -> 048c
15.. -> 159d
.... -> 26ae
.... -> 37bf
*/
auto doubling_y = [&](vc<mint>& A, int l, int r) -> void {
mint z = W[k / 2].inverse();
vc<mint> f(k);
FOR(i, l, r) {
FOR(j, k) f[j] = A[2 * n * j + i];
ntt(f, 1);
mint r = 1;
FOR(j, 1, k) r *= z, f[j] *= r;
ntt(f, 0);
FOR(j, k) A[2 * n * (k + j) + i] = f[j];
}
};
auto FFT_x = [&](vc<mint>& A, int l, int r) -> void {
vc<mint> f(2 * n);
FOR(j, l, r) {
move(A.begin() + 2 * n * j, A.begin() + 2 * n * (j + 1), f.begin());
ntt(f, 0);
move(all(f), A.begin() + 2 * n * j);
}
};
if (n <= k) {
doubling_y(P, 0, n), doubling_y(Q, 1, n);
FFT_x(P, 0, 2 * k), FFT_x(Q, 0, 2 * k);
} else {
FFT_x(P, 0, k), FFT_x(Q, 0, k);
doubling_y(P, 0, 2 * n), doubling_y(Q, 0, 2 * n);
}
FOR(i, 2 * n * k) Q[i] += 1;
FOR(i, 2 * n * k, 4 * n * k) Q[i] -= 1;
/*
048c -> 0248????
159d -> ....????
26ae
37bf
*/
vc<mint> F(2 * n), G(2 * n), f(n), g(n);
FOR(j, 2 * k) {
move(P.begin() + 2 * n * j, P.begin() + 2 * n * j + 2 * n, F.begin());
move(Q.begin() + 2 * n * j, Q.begin() + 2 * n * j + 2 * n, G.begin());
FOR(i, n) {
f[i] = W[i] * (F[2 * i] * G[2 * i + 1] - F[2 * i + 1] * G[2 * i]);
g[i] = G[2 * i] * G[2 * i + 1];
}
ntt(f, 1), ntt(g, 1);
fill(f.begin() + n / 2, f.end(), mint(0));
fill(g.begin() + n / 2, g.end(), mint(0));
move(all(f), P.begin() + n * j);
move(all(g), Q.begin() + n * j);
}
fill(P.begin() + 2 * n * k, P.end(), mint(0));
fill(Q.begin() + 2 * n * k, Q.end(), mint(0));
FOR(j, 4 * k) Q[n * j] = 0;
n /= 2, k *= 2;
}
FOR(i, k) P[i] = P[2 * i];
P.resize(k);
mint c = mint(1) / mint(k);
for (auto& x: P) x *= c;
ntt(P, 1);
reverse(all(P));
P.resize(m + 1);
return P;
}
// \sum_jwt[j][x^j]f^i を i=0,1,...,m
template <typename mint>
vc<mint> power_projection_0_garner(vc<mint> wt, vc<mint> f, int m) {
assert(len(f) == len(wt) && f[0] == mint(0));
int n = 1;
while (n < len(f)) n *= 2;
f.resize(n), wt.resize(n);
reverse(all(wt));
constexpr u32 p[] = {167772161, 469762049, 754974721};
using mint0 = modint<p[0]>;
using mint1 = modint<p[1]>;
using mint2 = modint<p[2]>;
vc<mint0> W0(2 * n);
vc<mint1> W1(2 * n);
vc<mint2> W2(2 * n);
{
// bit reverse order
vc<int> btr(2 * n);
int log = topbit(2 * n);
FOR(i, 2 * n) { btr[i] = (btr[i >> 1] >> 1) + ((i & 1) << (log - 1)); }
{
int t = mint0::ntt_info().fi;
mint0 r = mint0::ntt_info().se;
mint0 dw = r.inverse().pow((1 << t) / (4 * n));
mint0 w = 1;
for (auto& i: btr) { W0[i] = w, w *= dw; }
}
{
int t = mint1::ntt_info().fi;
mint1 r = mint1::ntt_info().se;
mint1 dw = r.inverse().pow((1 << t) / (4 * n));
mint1 w = 1;
for (auto& i: btr) { W1[i] = w, w *= dw; }
}
{
int t = mint2::ntt_info().fi;
mint2 r = mint2::ntt_info().se;
mint2 dw = r.inverse().pow((1 << t) / (4 * n));
mint2 w = 1;
for (auto& i: btr) { W2[i] = w, w *= dw; }
}
}
int k = 1;
vc<mint> P(2 * n), Q(2 * n);
FOR(i, n) P[i] = wt[i], Q[i] = -f[i];
while (n > 1) {
vc<mint0> P0(4 * n * k), Q0(4 * n * k);
vc<mint1> P1(4 * n * k), Q1(4 * n * k);
vc<mint2> P2(4 * n * k), Q2(4 * n * k);
FOR(i, 2 * n * k) P0[i] = P[i].val, Q0[i] = Q[i].val;
FOR(i, 2 * n * k) P1[i] = P[i].val, Q1[i] = Q[i].val;
FOR(i, 2 * n * k) P2[i] = P[i].val, Q2[i] = Q[i].val;
Q0[2 * n * k] = 1, Q1[2 * n * k] = 1, Q2[2 * n * k] = 1;
ntt(P0, 0), ntt(Q0, 0), ntt(P1, 0), ntt(Q1, 0), ntt(P2, 0), ntt(Q2, 0);
FOR(i, 2 * n * k) {
P0[i] = inv<mint0>(2) * W0[i]
* (P0[2 * i] * Q0[2 * i + 1] - P0[2 * i + 1] * Q0[2 * i]);
Q0[i] = Q0[2 * i] * Q0[2 * i + 1];
P1[i] = inv<mint1>(2) * W1[i]
* (P1[2 * i] * Q1[2 * i + 1] - P1[2 * i + 1] * Q1[2 * i]);
Q1[i] = Q1[2 * i] * Q1[2 * i + 1];
P2[i] = inv<mint2>(2) * W2[i]
* (P2[2 * i] * Q2[2 * i + 1] - P2[2 * i + 1] * Q2[2 * i]);
Q2[i] = Q2[2 * i] * Q2[2 * i + 1];
}
P0.resize(2 * n * k), Q0.resize(2 * n * k);
P1.resize(2 * n * k), Q1.resize(2 * n * k);
P2.resize(2 * n * k), Q2.resize(2 * n * k);
ntt(P0, 1), ntt(Q0, 1), ntt(P1, 1), ntt(Q1, 1), ntt(P2, 1), ntt(Q2, 1);
constexpr i128 K = u128(p[0]) * p[1] * p[2];
auto get = [&](mint0 a, mint1 b, mint2 c) -> mint {
i128 x = CRT3<u128, p[0], p[1], p[2]>(a.val, b.val, c.val);
i128 y = K - x;
return (x < y ? mint(x) : -mint(y));
};
fill(all(P), mint(0));
fill(all(Q), mint(0));
FOR(j, 2 * k) FOR(i, n / 2) {
int k = n * j + i;
P[k] = get(P0[k], P1[k], P2[k]);
Q[k] = get(Q0[k], Q1[k], Q2[k]);
}
Q[0] = 0;
n /= 2, k *= 2;
}
vc<mint> F(k);
FOR(i, k) F[i] = P[2 * i];
reverse(all(F));
F.resize(m + 1);
return F;
}
// \sum_j[x^j]f^i を i=0,1,...,m
template <typename mint>
vc<mint> power_projection(vc<mint> wt, vc<mint> f, int m) {
assert(len(f) == len(wt));
if (f.empty()) { return vc<mint>(m + 1, mint(0)); }
if (f[0] != mint(0)) {
mint c = f[0];
f[0] = 0;
vc<mint> A = power_projection(wt, f, m);
FOR(p, m + 1) A[p] *= fact_inv<mint>(p);
vc<mint> B(m + 1);
mint pow = 1;
FOR(q, m + 1) B[q] = pow * fact_inv<mint>(q), pow *= c;
A = convolution<mint>(A, B);
A.resize(m + 1);
FOR(i, m + 1) A[i] *= fact<mint>(i);
return A;
}
if (mint::can_ntt()) { return power_projection_0_ntt(wt, f, m); }
return power_projection_0_garner(wt, f, m);
}
#line 6 "poly/compositional_inverse.hpp"
// O(N^2)
template <typename mint>
vc<mint> compositional_inverse_old(const vc<mint>& F) {
const int N = len(F);
if (N == 0) return {};
assert(F[0] == mint(0));
if (N == 1) return F;
assert(F[0] == mint(0) && F[1] != mint(0));
vc<mint> DF = differentiate(F);
vc<mint> G(2);
G[1] = mint(1) / F[1];
while (len(G) < N) {
// G:= G(x)-(F(G(x))-x)/DF(G(x))
int n = len(G);
vc<mint> G1, G2;
{
vc<mint> FF(2 * n), GG(2 * n), DFF(n);
FOR(i, min<int>(len(F), 2 * n)) FF[i] = F[i];
FOR(i, min<int>(len(DF), n)) DFF[i] = DF[i];
FOR(i, n) GG[i] = G[i];
G1 = composition(FF, GG);
G2 = composition(DFF, G);
}
G1 = {G1.begin() + n, G1.end()};
G1 = fps_div(G1, G2);
G.resize(2 * n);
FOR(i, n) G[n + i] -= G1[i];
}
G.resize(N);
return G;
}
template <typename mint>
vc<mint> compositional_inverse(vc<mint> f) {
const int n = len(f) - 1;
if (n == -1) return {};
assert(f[0] == mint(0));
if (n == 0) return f;
assert(f[1] != mint(0));
mint c = f[1];
mint ic = c.inverse();
for (auto& x: f) x *= ic;
vc<mint> wt(n + 1);
wt[n] = 1;
vc<mint> A = power_projection<mint>(wt, f, n);
vc<mint> g(n);
FOR(i, 1, n + 1) g[n - i] = mint(n) * A[i] * inv<mint>(i);
g = fps_pow_1<mint>(g, -inv<mint>(n));
g.insert(g.begin(), 0);
mint pow = 1;
FOR(i, len(g)) g[i] *= pow, pow *= ic;
return g;
}
// G->F(G), G->DF(G) を与える
// len(G) まで求める. len(F) まで求めてもいいよ.
// 計算量は合成とだいたい同等
template <typename mint, typename F1, typename F2>
vc<mint> compositional_inverse(const vc<mint>& F, F1 comp_F, F2 comp_DF) {
const int N = len(F);
assert(N <= 0 || F[0] == mint(0));
assert(N <= 1 || F[1] != mint(0));
vc<mint> G(2);
G[1] = mint(1) / F[1];
while (len(G) < N) {
int n = len(G);
// G:= G(x)-(F(G(x))-x)/DF(G(x))
vc<mint> G2 = comp_DF(G);
G.resize(2 * n);
vc<mint> G1 = comp_F(G);
G1 = {G1.begin() + n, G1.end()};
G1 = fps_div(G1, G2);
FOR(i, n) G[n + i] -= G1[i];
}
G.resize(N);
return G;
}
#line 5 "graph/count/count_labeled_bridgeless.hpp"
// 橋のない連結グラフ
// https://oeis.org/A095983
// N=1: 1
// O(Nlog^2N)
// https://atcoder.jp/contests/ttpc2023/tasks/ttpc2023_p
template <typename mint>
vc<mint> count_labeled_bridgeless(int N) {
vc<mint> C = count_labeled_connected<mint>(N);
FOR(i, N + 1) C[i] *= fact_inv<mint>(i);
vc<mint> D(N + 1);
FOR(i, N + 1) D[i] = mint(i) * C[i];
vc<mint> E = fps_exp(D);
E.insert(E.begin(), mint(0));
E.pop_back();
// D(x)=B(E(x))
vc<mint> IE = compositional_inverse(E);
vc<mint> B = composition(D, IE);
vc<mint> A(N + 1);
FOR(i, 1, N + 1) A[i] = B[i] * inv<mint>(i);
FOR(i, 1, N + 1) A[i] *= fact<mint>(i);
return A;
}
// https://oeis.org/A095983
// N での値のみ, O(NlogN)
template <typename mint>
mint count_labeled_bridgeless_single(int N) {
if (N == 0) return 0;
vc<mint> C = count_labeled_connected<mint>(N);
FOR(i, N + 1) C[i] *= fact_inv<mint>(i);
vc<mint> D(N + 1);
FOR(i, N + 1) D[i] = mint(i) * C[i];
vc<mint> E = fps_exp(D);
E.insert(E.begin(), mint(0));
E.pop_back();
// D(x)=B(E(x))
// [x^N]B(x) を求めたい
// Lagrange Inversion
// N[x^N]D(IE(x))=[x^{-1}]D'(x)E(x)^{-N}
// =[x^{N-1}]D'(x)(E(x)/x)^{-N}
E.erase(E.begin());
E = fps_pow_1<mint>(E, -N);
D = differentiate(D);
mint ANS = 0;
FOR(i, N) ANS += D[i] * E[N - 1 - i];
ANS *= inv<mint>(N);
// [x^N]B(x) が出た
ANS *= inv<mint>(N);
ANS *= fact<mint>(N);
return ANS;
}