Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //Слава Україні, Героям слава
- #include <bits/stdc++.h>
- using namespace std;
- namespace fft {
- typedef long double dbl;
- struct num {
- dbl x, y;
- num() { x = y = 0; }
- num(dbl x, dbl y) : x(x), y(y) {}
- };
- inline num operator+ (num a, num b) { return num(a.x + b.x, a.y + b.y); }
- inline num operator- (num a, num b) { return num(a.x - b.x, a.y - b.y); }
- inline num operator* (num a, num b) { return num(a.x * b.x - a.y * b.y, a.x * b.y + a.y * b.x); }
- inline num conj(num a) { return num(a.x, -a.y); }
- int base = 1;
- vector<num> roots = { {0, 0}, {1, 0} };
- vector<int> rev = { 0, 1 };
- const dbl PI = acosl(-1.0);
- void ensure_base(int nbase) {
- if (nbase <= base) return;
- rev.resize(1 << nbase);
- for (int i = 0; i < (1 << nbase); i++) {
- rev[i] = (rev[i >> 1] >> 1) + ((i & 1) << (nbase - 1));
- }
- roots.resize(1 << nbase);
- while (base < nbase) {
- dbl angle = 2 * PI / (1 << (base + 1));
- for (int i = 1 << (base - 1); i < (1 << base); i++) {
- roots[i << 1] = roots[i];
- dbl angle_i = angle * (2 * i + 1 - (1 << base));
- roots[(i << 1) + 1] = num(cos(angle_i), sin(angle_i));
- }
- base++;
- }
- }
- void fft(vector<num>& a, int n = -1) {
- if (n == -1) {
- n = a.size();
- }
- assert((n & (n - 1)) == 0);
- int zeros = __builtin_ctz(n);
- ensure_base(zeros);
- int shift = base - zeros;
- for (int i = 0; i < n; i++) {
- if (i < (rev[i] >> shift)) {
- swap(a[i], a[rev[i] >> shift]);
- }
- }
- for (int k = 1; k < n; k <<= 1) {
- for (int i = 0; i < n; i += 2 * k) {
- for (int j = 0; j < k; j++) {
- num z = a[i + j + k] * roots[j + k];
- a[i + j + k] = a[i + j] - z;
- a[i + j] = a[i + j] + z;
- }
- }
- }
- }
- vector<num> fa, fb;
- vector<long long> multiply(vector<long long>& a, vector<long long>& b) {
- int need = a.size() + b.size() - 1;
- int nbase = 0;
- while ((1 << nbase) < need) nbase++;
- ensure_base(nbase);
- int sz = 1 << nbase;
- if (sz > (int)fa.size()) {
- fa.resize(sz);
- }
- for (int i = 0; i < sz; i++) {
- long long x = (i < (int)a.size() ? a[i] : 0);
- long long y = (i < (int)b.size() ? b[i] : 0);
- fa[i] = num(x, y);
- }
- fft(fa, sz);
- num r(0, -0.25 / sz);
- for (int i = 0; i <= (sz >> 1); i++) {
- int j = (sz - i) & (sz - 1);
- num z = (fa[j] * fa[j] - conj(fa[i] * fa[i])) * r;
- if (i != j) {
- fa[j] = (fa[i] * fa[i] - conj(fa[j] * fa[j])) * r;
- }
- fa[i] = z;
- }
- fft(fa, sz);
- vector<long long> res(need);
- for (int i = 0; i < need; i++) {
- res[i] = fa[i].x + 0.5;
- }
- return res;
- }
- vector<int> multiply_mod(vector<int>& a, vector<int>& b, int m, int eq = 0) {
- int need = a.size() + b.size() - 1;
- int nbase = 0;
- while ((1 << nbase) < need) nbase++;
- ensure_base(nbase);
- int sz = 1 << nbase;
- if (sz > (int)fa.size()) {
- fa.resize(sz);
- }
- for (int i = 0; i < (int)a.size(); i++) {
- int x = (a[i] % m + m) % m;
- fa[i] = num(x & ((1 << 15) - 1), x >> 15);
- }
- fill(fa.begin() + a.size(), fa.begin() + sz, num{ 0, 0 });
- fft(fa, sz);
- if (sz > (int) fb.size()) {
- fb.resize(sz);
- }
- if (eq) {
- copy(fa.begin(), fa.begin() + sz, fb.begin());
- }
- else {
- for (int i = 0; i < (int)b.size(); i++) {
- int x = (b[i] % m + m) % m;
- fb[i] = num(x & ((1 << 15) - 1), x >> 15);
- }
- fill(fb.begin() + b.size(), fb.begin() + sz, num{ 0, 0 });
- fft(fb, sz);
- }
- dbl ratio = 0.25 / sz;
- num r2(0, -1);
- num r3(ratio, 0);
- num r4(0, -ratio);
- num r5(0, 1);
- for (int i = 0; i <= (sz >> 1); i++) {
- int j = (sz - i) & (sz - 1);
- num a1 = (fa[i] + conj(fa[j]));
- num a2 = (fa[i] - conj(fa[j])) * r2;
- num b1 = (fb[i] + conj(fb[j])) * r3;
- num b2 = (fb[i] - conj(fb[j])) * r4;
- if (i != j) {
- num c1 = (fa[j] + conj(fa[i]));
- num c2 = (fa[j] - conj(fa[i])) * r2;
- num d1 = (fb[j] + conj(fb[i])) * r3;
- num d2 = (fb[j] - conj(fb[i])) * r4;
- fa[i] = c1 * d1 + c2 * d2 * r5;
- fb[i] = c1 * d2 + c2 * d1;
- }
- fa[j] = a1 * b1 + a2 * b2 * r5;
- fb[j] = a1 * b2 + a2 * b1;
- }
- fft(fa, sz);
- fft(fb, sz);
- vector<int> res(need);
- for (int i = 0; i < need; i++) {
- long long aa = fa[i].x + 0.5;
- long long bb = fb[i].x + 0.5;
- long long cc = fa[i].y + 0.5;
- res[i] = (aa + ((bb % m) << 15) + ((cc % m) << 30)) % m;
- }
- return res;
- }
- vector<int> square_mod(vector<int>& a, int m) {
- return multiply_mod(a, a, m, 1);
- }
- }
- struct Centroid {
- vector<vector<pair<int, int>>> adj;
- vector<long long> ans;
- vector<bool> vis;
- vector<int> par, sz;
- int n;
- Centroid(int n_) {
- n = n_;
- adj.resize(n + 1); vis.resize(n + 1);
- par.resize(n + 1); sz.resize(n + 1);
- }
- void add(int a, int b, int c) {
- adj[a].push_back({b, c});
- adj[b].push_back({a, c});
- }
- int dfs_sz(int v, int p = -1) {
- if(vis[v]) {
- return 0;
- }
- sz[v] = 1;
- for(auto x : adj[v]) {
- if(x.first != p) {
- sz[v] += dfs_sz(x.first, v);
- }
- }
- return sz[v];
- }
- int centroid(int v, int p, int size) {
- for(auto x : adj[v]) {
- if(x.first != p and !vis[x.first] and sz[x.first] > size / 2) {
- return centroid(x.first, v, size);
- }
- }
- return v;
- }
- void dfs(vector<long long> &path, int i, int ok, int p = -1, int d = 1) {
- if(ok) {
- if(path.size() > d) {
- path[d]++;
- } else {
- path.push_back(1);
- }
- }
- for(auto j : adj[i]) {
- if(j.first != p and !vis[j.first]) {
- dfs(path, j.first, j.second, i, d + j.second);
- }
- }
- }
- void decomp(int i = 1) {
- int c = centroid(i, i, dfs_sz(i));
- vis[c] = true;
- vector<long long> s = {0}, sqs = {0};
- for(auto j : adj[c]) {
- if(!vis[j.first]) {
- vector<long long> cur = {0};
- dfs(cur, j.first, j.second, -1, j.second);
- if(s.size() < cur.size()) s.resize(cur.size());
- if(ans.size() < cur.size()) ans.resize(cur.size());
- for(int i = 0; i < (int)cur.size(); i++) {
- s[i] += cur[i];
- if(j.second) ans[i] += cur[i];
- }
- cur = fft::multiply(cur, cur);
- if(sqs.size() < cur.size()) sqs.resize(cur.size());
- for(int i = 0; i < (int)cur.size(); i++) {
- sqs[i] += cur[i];
- }
- }
- }
- //s[0] = 1;
- s = fft::multiply(s, s);
- for(int i = 0; i < (int)sqs.size(); i++) {
- s[i] -= sqs[i];
- }
- if(ans.size() < s.size()) ans.resize(s.size());
- for(int i = 1; i < (int)s.size(); i++) {
- ans[i] += s[i] >> 1;
- }
- for(auto j : adj[c]) {
- if(!vis[j.first]) {
- decomp(j.first);
- }
- }
- vis[c] = false;
- }
- };
- long long binexp(long long a, long long n, int mod) {
- long long res = 1;
- while(n) {
- if(n & 1) {
- res = (res * a) % mod;
- }
- n >>= 1;
- a = (a * a) % mod;
- }
- return res;
- }
- const int N = 4e5 + 7;
- namespace ntt {
- long long w[N], k, nrev;
- inline void init(int n, int root, int mod) {
- w[0] = 1;
- k = binexp(root, (mod - 1) / n, mod);
- nrev = binexp(n, mod - 2, mod);
- for(int i = 1; i <= n; i++) {
- w[i] = (w[i - 1] * k) % mod;
- }
- }
- inline void ntt(vector<long long> &a, int n, int mod, bool inv = false) {
- a.resize(n);
- for(int i = 0, j = 0; i < n; i++) {
- if(i > j) swap(a[i], a[j]);
- for(int l = n / 2; (j ^= l) < l; l >>= 1);
- }
- for(int i = 2; i <= n; i <<= 1) {
- for(int j = 0; j < n; j += i) {
- for(int l = 0; l < i / 2; l++) {
- int x = j + l, y = j + l + (i / 2), z = (n / i) * l;
- long long tmp = (a[y] * w[(inv ? (n - z) : z)]) % mod;
- a[y] = (a[x] - tmp + mod) % mod;
- a[x] = (a[j + l] + tmp) % mod;
- }
- }
- }
- if(inv) {
- for(int i = 0; i < n; i++) {
- a[i] = (a[i] * nrev) % mod;
- }
- }
- }
- vector<long long> multiply(vector<long long>& a, vector<long long>& b, int n, int root = 3, int mod = 998244353) {
- init(2 * n, root, mod);
- a.resize(2 * n);
- b.resize(2 * n);
- ntt(a, 2 * n, mod);
- ntt(b, 2 * n, mod);
- vector<long long> ans(2 * n);
- for(int i = 0; i < 2 * n; i++) {
- ans[i] = (a[i] * b[i]) % mod;
- }
- ntt(ans, 2 * n, mod, true);
- return ans;
- }
- vector<long long> multiply_garner(vector<long long> &a, vector<long long> &b, int n, int mod) {
- vector<long long> primes = {1004535809, 998244353, 985661441};
- vector<long long> x[3], y[3], z[3];
- for(int p = 0; p < 3; p++) {
- x[p].resize(n);
- y[p].resize(n);
- for(int i = 0; i < n; i++) {
- x[p][i] = a[i] % primes[p];
- y[p][i] = b[i] % primes[p];
- }
- }
- for(int p = 0; p < 3; p++) {
- z[p] = multiply(x[p], y[p], n, 3, primes[p]);
- }
- vector<long long> ans(n);
- long long r01 = binexp(primes[0], primes[1] - 2, primes[1]);
- long long r02 = binexp(primes[0], primes[2] - 2, primes[2]);
- long long r12 = binexp(primes[1], primes[2] - 2, primes[2]);
- for(int i = 0; i < n; i++) {
- long long a0 = z[0][i];
- long long a1 = (((z[1][i] - z[0][i] + 2 * primes[1]) % primes[1]) * r01) % primes[1];
- long long a2 = (((z[2][i] - z[0][i] + 2 * primes[2]) % primes[2]) * r02) % primes[2];
- a2 = ((a2 - a1 + 2 * primes[2]) % primes[2]) * r12 % primes[2];
- long long res = a0 % mod;
- res = (res + a1 * (primes[0] % mod)) % mod;
- res = (res + a2 * ((primes[0] % mod) * (primes[1] % mod) % mod)) % mod;
- ans[i] = res;
- }
- return ans;
- }
- }
- const int mod = 998244353;
- long long fact[N], ifact[N];
- int main() {
- ios_base::sync_with_stdio(false);
- cin.tie(nullptr);
- fact[0] = 1;
- for(long long i = 1; i < N; i++) {
- fact[i] = fact[i - 1] * i % mod;
- }
- ifact[N - 1] = binexp(fact[N - 1], mod - 2, mod);
- for(long long i = N - 2; i >= 0; i--) {
- ifact[i] = (ifact[i + 1] * (i + 1)) % mod;
- }
- int n;
- cin >> n;
- Centroid cent(n);
- for(int i = 1; i < n; i++) {
- int a, b, c;
- cin >> a >> b >> c;
- cent.add(a, b, c);
- }
- cent.decomp();
- vector<long long> b = cent.ans, a(n);
- b.resize(n);
- cout << b[1] << " ";
- for(int i = 2; i < (int)b.size(); i++) {
- b[i] %= mod;
- b[i] = (b[i] * fact[i - 2]) % mod;
- }
- for(int i = 0; i < n; i++) {
- a[i] = ifact[i];
- }
- reverse(a.begin(), a.end());
- int x = 1;
- while(x < (int)a.size()) {
- x <<= 1;
- }
- a.resize(x);
- b.resize(x);
- vector<long long> c = ntt::multiply(a, b, x);
- for(int i = 2; i <= n - 1; i++) {
- cout << c[n + i - 1] * ifact[i - 2] % mod << " \n"[i == n - 1];
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement