多項式對數函式學習筆記
阿新 • • 發佈:2018-12-28
最近一直在學一些多項式的板子…
前置技能:多項式求逆
問題是對於 ,已知 ,求 。
用複合函式的求導法則,那麼原式轉換為:
右邊那個東西可以用多項式求逆來做,求完以後積分就好了。
積分:
求導:
Codes
#include <bits/stdc++.h>
using namespace std;
const int N = 1 << 18 | 1;
const int mod = 998244353;
int g[N], invg[N], A[N], B[N], rev[N];
inline int add(int x, int y) { return (x += y) < mod ? x : x - mod; }
inline int qpow(int _, int __) {
int ___ = 1;
for (; __; __ >>= 1, _ = 1ll * _ * _ % mod)
if (__ & 1) ___ = 1ll * ___ * _ % mod;
return ___;
}
inline void NTT(int *a, int n, int fh) {
for (int i = 0; i < n; ++ i)
if (i < rev[i]) swap(a[i], a[rev[i]]);
for (int limit = 2, wn; limit <= n; limit <<= 1) {
wn = qpow(fh ^ 1 ? qpow(3, mod - 2) : 3, (mod - 1) / limit);
for (int j = 0, w = 1; j < n; j += limit, w = 1)
for (int i = j; i < j + (limit >> 1); ++ i, w = 1ll * w * wn % mod) {
int a1 = a[i], a2 = 1ll * a[i + (limit >> 1)] * w % mod;
a[i] = add(a1, a2), a[i + (limit >> 1)] = add(a1, mod - a2);
}
}
if (fh ^ 1) for (int i = 0, inv = qpow(n, mod - 2); i < n; ++ i)
a[i] = 1ll * a[i] * inv % mod;
}
inline void Invpoly(int *a, int *b, int len) {
if (len ^ 1) {
Invpoly(a, b, len >> 1);
int k = 0, limit = 1;
while (limit < len * 2) limit <<= 1, ++ k;
for (int i = 0; i < limit; ++ i) {
A[i] = B[i] = 0;
rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << (k - 1));
}
for (int i = 0; i < len; ++ i)
A[i] = a[i], B[i] = b[i];
NTT(A, limit, 1), NTT(B, limit, 1);
for (int i = 0; i < limit; ++ i)
A[i] = 1ll * A[i] * B[i] % mod * B[i] % mod;
NTT(A, limit, -1);
for (int i = 0; i < len; ++ i)
b[i] = add(b[i], add(b[i], mod - A[i]));
}
else b[0] = qpow(a[0], mod - 2);
}
inline void Derpoly(int *a, int len) {
for (int i = 0; i < len - 1; ++ i)
a[i] = 1ll * (i + 1) * (a[i + 1]) % mod;
a[len - 1] = 0;
}
inline void Intpoly(int *a, int len) {
for (int i = len - 1; i; -- i)
a[i] = 1ll * a[i - 1] * qpow(i, mod - 2) % mod;
a[0] = 0;
}
int main() {
#ifdef ylsakioi
freopen("4725.in", "r", stdin);
freopen("4725.out", "w", stdout);
#endif
int limit = 1, k = 0, n;
scanf("%d", &n);
while (limit < n * 2) limit <<= 1, ++ k;
for (int i = 0; i < n; ++ i)
scanf("%d", &g[i]);
Invpoly(g, invg, limit >> 1);
Derpoly(g, limit >> 1);
for (int i = 0; i < limit; ++ i)
rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << (k - 1));
NTT(g, limit, 1), NTT(invg, limit, 1);
for (int i = 0; i < limit; ++ i)
g[i] = 1ll * g[i] * invg[i] % mod;
NTT(g, limit, -1);
Intpoly(g, limit);
for (int i = 0; i < n; ++ i)
printf("%d ", g[i]);
return 0;
}