1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
|
#include <cstring> #include <cstdio> #include <algorithm>
using namespace std;
const int maxn = 100010; const int mod = 998244353; const int g = 3;
int (int x, int y) { int ret = 1; while (y) { if (y & 1) ret = 1LL*ret*x%mod; x = 1LL*x*x%mod; y >>= 1; } return ret; }
int n = 0;
struct poly { int *a, len; poly(int l) { len = l; a = new int[l]; for (int i = 0; i < l; i++) a[i] = 0; } };
int w_a[maxn*4], w_b[maxn*4], w_c[maxn*4], rev[maxn*4];
void ntt(int *a, int t, int ty) { int len = (1 << t); for (int i = 1; i < len; i++) rev[i] = (rev[i>>1]>>1)|((i&1)<<(t-1)); for (int i = 0; i < len; i++) if (rev[i] > i) swap(a[i], a[rev[i]]); for (int l = 2; l <= len; l <<= 1) { int wn = qpow(g, (mod-1)/l); for (int s = 0; s < len; s += l) { int w = 1; for (int i = s; i < (s+(l>>1)); i++) { int v1 = a[i], v2 = 1LL*w*a[i+(l>>1)]%mod; a[i] = (v1+v2) % mod; a[i+(l >> 1)] = (v1-v2+mod)%mod; w = 1LL*w*wn%mod; } } } if (ty == -1) { for (int i = 1; i < len/2; i++) swap(a[i], a[len-i]); int r = qpow(len, mod-2); for (int i = 0; i < len; i++) a[i] = 1LL*a[i]*r%mod; } }
poly operator*(poly a, poly b) { poly ret(a.len + b.len - 1); int t = 0; while ((1<<t) < ret.len) ++ t; for (int i = 0; i < (1<<t); i++) w_a[i] = w_b[i] = 0; for (int i = 0; i < a.len; i++) w_a[i] = a.a[i]; for (int i = 0; i < b.len; i++) w_b[i] = b.a[i]; ntt(w_a, t, 1); ntt(w_b, t, 1); for (int i = 0; i < (1<<t); i++) w_c[i] = 1LL*w_a[i]*w_b[i]%mod; ntt(w_c, t, -1); for (int i = 0; i < ret.len; i++) ret.a[i] = w_c[i]; return ret; }
poly poly_inverse(poly a) { if (a.len == 1) { poly ret(1); ret.a[0] = qpow(a.a[0], mod-2); return ret; } int nl = (a.len+1)/2; poly na(nl); for (int i = 0; i < nl; i++) na.a[i] = a.a[i]; poly r = poly_inverse(na); poly t = r*a; t.len = a.len; for (int i = 0; i < t.len; i++) t.a[i] = (mod-t.a[i])%mod; t.a[0] = (t.a[0] + 2) % mod; poly ret = t*r; ret.len = a.len; return ret; }
poly poly_ln(poly a) { poly t(a.len-1); for (int i = 1; i < a.len; i++) { t.a[i-1] = 1LL * a.a[i] * i % mod; } poly x = poly_inverse(a); poly s = x*t; s.len = a.len; poly ret(a.len); for (int i = 1; i < a.len; i++) { ret.a[i] = 1LL*qpow(i, mod-2)*s.a[i-1]%mod; } return ret; }
int main() { scanf("%d", &n); poly A(n); for (int i = 0; i < n; i++) scanf("%d", &A.a[i]); poly P = poly_ln(A); for (int i = 0; i < n; i++) printf("%d ", P.a[i]); printf("n"); return 0; }
|
近期评论