P4725 【模板】多項式對數函數
阿新 • • 發佈:2019-01-16
min () tchar amp eve swap rev push_back urn \(\color{#0066ff}{輸出格式}\)
\(B(x)=\ln(A(x))\)
\(\color{#0066ff}{ 題目描述 }\)
給出 \(n-1\) 次多項式 \(A(x)\),求一個 \(\bmod{\:x^n}\)下的多項式 \(B(x)\),滿足 \(B(x) \equiv \ln A(x)\)
在 \(\text{mod } 998244353\)下進行,且 \(a_i \in [0, 998244353] \cap \mathbb{Z}\)
\(\color{#0066ff}{輸入格式}\)
第一行一個整數 \(n\).
下一行有 \(n\) 個整數,依次表示多項式的系數 \(a_0, a_1, \cdots, a_{n-1}\)
保證 \(a_0 = 1\).
\(\color{#0066ff}{輸出格式}\)
輸出 \(n\) 個整數,表示答案多項式中的系數 \(a_0, a_1, \cdots, a_{n-1}\).
\(\color{#0066ff}{輸入樣例}\)
6
1 927384623 878326372 3882 273455637 998233543
\(\color{#0066ff}{輸出樣例}\)
0 927384623 817976920 427326948 149643566 610586717
\(\color{#0066ff}{數據範圍與提示}\)
對於 \(100\%\)的數據,\(n \le 10^5\).
\(\color{#0066ff}{ 題解 }\)
推一下式子
\(B(x)=\ln(A(x))\)
\(B'(x)=\frac{A'(x)}{A(x)}\)
\(B(x)=\int \frac{A'(x)}{A(x)}\)
積分相當於逆求導,由於是多項式,很好求
先求個逆,再求個導,再FFT一下,再積分一下就行了
#include<bits/stdc++.h> #define LL long long LL in() { char ch; LL x = 0, f = 1; while(!isdigit(ch = getchar()))(ch == '-') && (f = -f); for(x = ch ^ 48; isdigit(ch = getchar()); x = (x << 1) + (x << 3) + (ch ^ 48)); return x * f; } using std::vector; const int mod = 998244353; const int maxn = 4e5 + 10; int len, r[maxn]; LL ksm(LL x, LL y) { LL re = 1LL; while(y) { if(y & 1) re = re * x % mod; x = x * x % mod; y >>= 1; } return re; } void FNTT(vector<int> &A, int flag) { A.resize(len); for(int i = 0; i < len; i++) if(i < r[i]) std::swap(A[i], A[r[i]]); for(int l = 1; l < len; l <<= 1) { int w0 = ksm(3, (mod - 1) / (l << 1)); for(int i = 0; i < len; i += (l << 1)) { int w = 1, a0 = i, a1 = i + l; for(int k = 0; k < l; k++, a0++, a1++, w = 1LL * w * w0 % mod) { int tmp = 1LL * A[a1] * w % mod; A[a1] = ((A[a0] - tmp) % mod + mod) % mod; A[a0] = (A[a0] + tmp) % mod; } } } if(flag == -1) { std::reverse(A.begin() + 1, A.end()); int inv = ksm(len, mod - 2); for(int i = 0; i < len; i++) A[i] = 1LL * inv * A[i] % mod; } } vector<int> operator * (vector<int> A, vector<int> B) { int tot = A.size() + B.size() - 1; for(len = 1; len <= tot; len <<= 1); for(int i = 0; i < len; i++) r[i] = (r[i >> 1] >> 1) | ((i & 1) * (len >> 1)); FNTT(A, 1), FNTT(B, 1); vector<int> ans; ans.resize(len); for(int i = 0; i < len; i++) ans[i] = 1LL * A[i] * B[i] % mod; FNTT(ans, -1); ans.resize(tot); return ans; } vector<int> operator - (const vector<int> &A, const vector<int> &B) { vector<int> ans; for(int i = 0; i < (int)std::min(A.size(), B.size()); i++) ans.push_back(A[i] - B[i]); if(A.size() > B.size()) for(int i = B.size(); i < (int)A.size(); i++) ans.push_back(A[i]); if(A.size() < B.size()) for(int i = A.size(); i < (int)B.size(); i++) ans.push_back(-B[i]); return ans; } vector<int> inv(const vector<int> &A) { if(A.size() == 1) { vector<int> ans; ans.push_back(ksm(A[0], mod - 2)); return ans; } int n = A.size(), _ = (n + 1) >> 1; vector<int> ans, B = A; ans.push_back(2); B.resize(_); B = inv(B); ans = B * (ans - A * B); ans.resize(n); return ans; } vector<int> getd(const vector<int> &A) { vector<int> ans; ans.resize(A.size() - 1); for(int i = 1; i < (int)A.size(); i++) ans[i - 1] = 1LL * i * A[i] % mod; return ans; } vector<int> geti(const vector<int> &A) { vector<int> ans; ans.resize(A.size() + 1); for(int i = 1; i < (int)ans.size(); i++) ans[i] = 1LL * A[i - 1] * ksm(i, mod - 2) % mod; return ans; } int main() { int n = in(); vector<int> a, b, c; for(int i = 0; i < n; i++) a.push_back(in()); b = inv(a); a = getd(a); c = a * b; c = geti(c); for(int i = 0; i < n; i++) printf("%d%c", c[i], i == n - 1? '\n' : ' '); return 0; }
P4725 【模板】多項式對數函數