[洛谷P4725]【模板】多项式对数函数

题目大意:给出$n-1$次多项式$A(x)$,求一个 $mod{x^n}$下的多项式$B(x)$,满足$B(x) equiv ln A(x)$。在$mod{998244353}$下进行。保证$A[0]=1$

题解:
$$
B(x)=ln A(x)\
B'(x)=dfrac{A'(x)}{A(x)}\
B(x)=intdfrac{A'(x)}{A(x)}mathrm{dx}
$$
卡点:

C++ Code:

#include <cstdio>
#include <algorithm>
#define maxn 262144 + 10
const int mod = 998244353, G = 3;
int n;
int g[maxn], f[maxn];
inline int pw(int base, long long p) {
	p %= mod - 1, base %= mod;
	int res = 1;
	for (; p; p >>= 1, base = 1ll * base * base % mod) if (p & 1) res = 1ll * res * base % mod;
	return res;
}
inline int INV(int x) {
	return pw(x, mod - 2);
}
namespace Polynomial {
	int lim, ilim, s, rev[maxn];
	int C[maxn], Wn[maxn];
	inline void init(int n) {
		s = -1, lim = 1; while (lim < n) lim <<= 1, s++;
		ilim = ::INV(lim);
		for (int i = 1; i < lim; i++) rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << s);
		int tmp = pw(G, (mod - 1) / lim);
		Wn[0] = 1; for (int i = 1; i <= lim; i++) Wn[i] = 1ll * Wn[i - 1] * tmp % mod;
	}
	inline void up(int &a, int b) {if ((a += b) >= mod) a -= mod;}
	inline void NTT(int *A, int op) {
		for (int i = 0; i < lim; i++) if (i < rev[i]) std::swap(A[i], A[rev[i]]);
		for (int mid = 1; mid < lim; mid <<= 1) {
			int t = lim / mid >> 1;
			for (int i = 0; i < lim; i += (mid << 1)) {
				for (int j = 0; j < mid; j++) {
					int W = op ? Wn[t * j] : Wn[lim - t * j];
					int X = A[i + j], Y = 1ll * W * A[i + j + mid] % mod;
					up(A[i + j], Y), up(A[i + j + mid] = X, mod - Y);
				}
			}
		}
		if (!op) for (int i = 0; i < lim; i++) A[i] = 1ll * A[i] * ilim % mod;
	}
	void INV(int *A, int *B, int n) {
		if (n == 1) {B[0] = ::INV(A[0]); return ;}
		INV(A, B, n + 1 >> 1), init(n << 1);
		for (int i = 0; i < n; i++) C[i] = A[i];
		for (int i = n; i < lim; i++) C[i] = B[i] = 0;
		NTT(B, 1), NTT(C, 1);
		for (int i = 0; i < lim; i++) B[i] = (2 + mod - 1ll * B[i] * C[i] % mod) * B[i] % mod;
		NTT(B, 0);
		for (int i = n; i < lim; i++) B[i] = 0;
	}
	inline void DER(int *A, int *B, int n) {
		B[n] = 0; for (int i = 1; i < n; i++) B[i - 1] = 1ll * A[i] * i % mod;
	}
	inline void INT(int *A, int *B, int n) {
		B[0] = 0; for (int i = 1; i < n; i++) B[i] = 1ll * A[i - 1] * ::INV(i) % mod;
	}
	
	int D[maxn];
	inline void LN(int *A, int *B, int len) {
		DER(A, B, len);
		INV(A, D, len);
		init(n << 1);
		NTT(B, 1), NTT(D, 1);
		for (int i = 0; i < lim; i++) D[i] = 1ll * B[i] * D[i] % mod;
		NTT(D, 0);
		INT(D, B, len);
		for (int i = len; i < lim; i++) B[i] = 0;
	}
}
int main() {
	scanf("%d", &n);
	for (int i = 0; i < n; i++) scanf("%d", &g[i]);
	Polynomial::LN(g, f, n);
	for (int i = 0; i < n; i++) printf("%d ", f[i]); puts("");
	return 0;
}

  

原文地址:https://www.cnblogs.com/Memory-of-winter/p/9717954.html