P4725 【模板】多项式对数函数

\(\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;
}

原文地址:https://www.cnblogs.com/olinr/p/10277143.html

时间: 2024-11-10 12:55:56

P4725 【模板】多项式对数函数的相关文章

luogu P4725 多项式对数函数 (模板题、FFT、多项式求逆、求导和积分)

手动博客搬家: 本文发表于20181125 13:25:03, 原地址https://blog.csdn.net/suncongbo/article/details/84487306 题目链接: https://www.luogu.org/problemnew/show/P4725 题目大意: 给定一个\(n\)次多项式\(A(x)\), 求一个\(n\)次多项式\(B(x)\)满足\(B(x)\equiv \ln A(x) (\mod x^n)\) 题解: 神数学模板题-- 数学真奇妙! 前驱

Luogu 4725 【模板】多项式对数函数

继续补全模板. 要求 $$g(x) = ln f(x)$$ 两边求导, $$g'(x) = \frac{f'(x)}{f(x)}$$ 然后左转去把多项式求导和多项式求逆的模板复制过来,就可以计算出$g'(x)$,接下来再对$g'(x)$求不定积分即可. 虽然我也不是很会不定积分,但是这就是求导的逆过程,相当于把求完导之后的函数搞回去. 因为$(a_ix^i)' = ia_ix^{i - 1}$,所以反向算一下就好. 求导的时间复杂度是$O(n)$,积分的时间复杂度是$O(nlogn)$,总时间复

luogu 4725 【模板】多项式对数函数(多项式 ln)

Code: #include <cstdio> #include <string> #include <algorithm> #include <cstring> #include <vector> #define setIO(s) freopen(s".in","r",stdin) typedef long long ll; const int maxn=2100005; const ll mod=998

[模板] 多项式全家桶

注意:以下所有说明均以帮助理解模板为目的,不保证正确性. 多项式求逆 已知$A(x)$,求满足$A(x)B(x)=1\ (mod\ x^n)$的B(以下为了方便假设n是2的幂) 考虑倍增,假设已经求出$A(x)B_0(x)=1\ (mod\ x^{n/2})$ $$A(x)(B(x)-B_0(x))=0\ (mod\ x^{n/2})$$ $$(B(x)-B_0(x))=0\ (mod\ x^{n/2})$$ $$(B(x)-B_0(x))^2=0\ (mod\ x^n)$$ $$B^2(x)-

洛谷.3803.[模板]多项式乘法(FFT)

题目链接:洛谷.LOJ. FFT相关:快速傅里叶变换(FFT)详解.FFT总结.从多项式乘法到快速傅里叶变换. #include <cmath> #include <cctype> #include <cstdio> #include <algorithm> #define gc() getchar() const int N=1e6+5; const double PI=acos(-1); int n,m; struct Complex { double

[模板] 多项式: 乘法/求逆/分治fft/微积分/ln/exp/幂

多项式 代码 const int nsz=(int)4e5+50; const ll nmod=998244353,g=3,ginv=332748118ll; //basic math ll qp(ll a,ll b){ ll res=1; for(;b;a=a*a%nmod,b>>=1)if(b&1)res=res*a%nmod; return res; } ll inv(ll n){ return qp(n,nmod-2); } //polynomial operations //

多项式模板整理

多项式乘法 FFT模板 时间复杂度\(O(n\log n)\). 模板: void FFT(Z *a,int x,int K){ static int rev[N],lst; int n=(1<<x); if(n!=lst){ for(int i=0;i<n;i++)rev[i]=(rev[i>>1]>>1)|((i&1)<<x-1); lst=n; } for(int i=0;i<n;i++)if(i<rev[i])swap(a[

关于万恶的多项式

模板: 1 //Achen 2 #include<algorithm> 3 #include<iostream> 4 #include<cstring> 5 #include<cstdlib> 6 #include<vector> 7 #include<cstdio> 8 #include<queue> 9 #include<cmath> 10 #include<set> 11 #include&l

@算法 - [email&#160;protected] 牛顿迭代法的应用——多项式开方,对数,指数,三角与幂函数

目录 @0 - 参考资料@ @0.5 - 多项式平方根@ @1 - 牛顿迭代法@ @数学上的定义@ @对于多项式的定义@ @2 - 牛顿迭代的应用@ @重新推导 - 多项式逆元@ @重新推导 - 多项式平方根@ @多项式对数函数@ @多项式指数函数@ @多项式幂函数@ @多项式三角函数@ @3 - 一些参考代码@(留坑待填) @4 - 算法应用@(留坑待填) @0 - 参考资料@ Miskcoo's Space 的讲解 Picks 的讲解 @0.5 - 多项式平方根@ 已知一个多项式 \(A(x