题解 P4725 【模板】多项式对数函数(多项式 ln)
前置知识:求导与积分。
求导公式$$x^{a'}=ax^{a-1}$$ 不定积分公式$$\int x^adx=\dfrac{1}{a+1}x^{a+1}$$ 然后开始推式子。$$G(x)\equiv \ln(F(x))(\bmod\ x^n)$$ 令$$f(x)=\text{ln}(x)$$$$G(x)\equiv f(F(x))(\bmod\ x^n)$$
观察发现这是个复合函数,两边求导得$$G(x)'\equiv f'(F(x))F'(x)(\bmod\ x^n)$$ 由 $\text{ln}'(x)=\frac{1}{x}$ 得$$G'(x)\equiv \dfrac{F'(x)}{F(x)}(\bmod\ x^n)$$
两边再积起来$$\therefore \int G'(x)\equiv\int\dfrac{F'(x)}{F(x)}(\bmod\ x^n)$$$$\therefore G(x)\equiv\int\dfrac{F'(x)}{F(x)}(\bmod\ x^n)$$ 多项式求逆即可,时间复杂度 $O(n\log n)$。
#include <bits/stdc++.h>
using namespace std;
namespace IO {
//read and write
} using namespace IO;
const int N = 2.7e5 + 10;
namespace Polynomial {
const int P = 998244353, G = 3, Gi = 332748118, inv2 = 499122177;
int lim, rev[N], a[N], b[N], c[N], d[N], e[N], f[N];
int qpow(int n, int k) {
int res = 1;
for(; k; n = 1ll * n * n % P, k >>= 1)
if(k & 1) res = 1ll * res * n % P;
return res;
}
void NTT(int *f, int T) {
for(int i = 0; i < lim; i++)
if(i < rev[i])
swap(f[i], f[rev[i]]);
for(int mid = 1; mid < lim; mid <<= 1) {
int wn = qpow(T == 1 ? G : Gi, (P - 1) / (mid << 1));
int len = mid << 1;
for(int i = 0; i < lim; i += (mid << 1)) {
int w = 1;
for(int j = 0; j < mid; j++, w = 1ll * w * wn % P) {
int x = f[i + j], y = 1ll * w * f[i + j + mid] % P;
f[i + j] = (x + y) % P;
f[i + j + mid] = (x - y + P) % P;
}
}
}
if(T == -1) {
int inv = qpow(lim, P - 2);
for(int i = 0; i < lim; i++)
f[i] = 1ll * f[i] * inv % P;
}
}
void init(int n) {
for(lim = 1; lim < n; lim <<= 1);
for(int i = 0; i < lim; i++)
rev[i] = (rev[i >> 1] >> 1) | ((i & 1) * (lim >> 1));
}
void mul(int *f, int *g, int *h, int n, int m) {
static int a[N], b[N];
init(n + m - 1);
memset(a, 0, lim << 2);
memcpy(a, f, n << 2);
memset(b, 0, lim << 2);
memcpy(b, g, m << 2);
NTT(a, 1), NTT(b, 1);
for(int i = 0; i < lim; i++)
h[i] = 1ll * a[i] * b[i] % P;
NTT(h, -1);
}
void inv(int *f, int *g, int n) {
if(n == 1) { g[0] = qpow(f[0], P - 2); return; }
inv(f, g, n + 1 >> 1);
init(n << 1);
copy(f, f + n, a);
fill(a + n, a + lim, 0);
NTT(a, 1), NTT(g, 1);
for(int i = 0; i < lim; i++)
g[i] = (2 - 1ll * a[i] * g[i] % P + P) % P * g[i] % P;
NTT(g, -1);
fill(g + n, g + lim, 0);
}
void dev(int *f, int *g, int n) {
for(int i = 1; i < n; i++)
g[i - 1] = 1ll * i * f[i] % P;
g[n - 1] = 0;
}
void invdev(int *f, int *g, int n) {
for(int i = n - 1; i; i--)
g[i] = 1ll * f[i - 1] * qpow(i, P - 2) % P;
g[0] = 0;
}
void ln(int *f, int *g, int n) {
static int a[N];
init(n << 1);
memset(a, 0, n << 2);
inv(f, a, n);
dev(f, g, n);
mul(g, a, g, n, n);
invdev(g, g, n);
}
}
using Polynomial::ln;
int n, f[N], g[N];
int main() {
n = read();
for(int i = 0; i < n; i++) f[i] = read();
ln(f, g, n);
for(int i = 0; i < n; i++) write(g[i]), putc(' ');
flush();
return 0;
}

浙公网安备 33010602011771号