LG4725 [template] polynomial logarithmic function (polynomial ln)

P4725 [template] polynomial logarithmic function (polynomial ln)

Title Description

$ N-1 $ given order polynomial $ A (x) $, seeking a $ \ bmod {\: x ^ n} under the polynomial $ B $ (x) $, satisfying $ B (x) \ equiv \ ln A (x) $.

Carried out at $ \ text {mod} 998244353 $, and $ a_i \ in [0, 998244353] \ cap \ mathbb {Z} $

Input and output formats

Input formats:

A first line integer $ n $.

The next row has n-$ $ integers, respectively for the coefficients of the polynomial $ a_0, a_1, \ cdots, a_ {n-1} $.

Guarantee $ a_0 = 1 $.

Output formats:

$ $ Integers n-output, answers represent the coefficients in the polynomial $ a_0, a_1, \ cdots, a_ {n-1} $.

Sample input and output

Input Sample # 1: Copy
6
1 927384623 878326372 3882 273455637 998233543
Output Sample # 1: Copy
0 927384623 817976920 427326948 149643566 610586717

Explanation

For $ 100 \% $ data, $ n \ le 10 ^ 5 $.

answer

Finally I understand ...... polynomial \ (\ mod x ^ n \ ) with integer \ (\ mod p \) , as should always pay attention to the modulo the number of terms that are reserved. If the number of items remain too much will cause the calculation point value is not accurate.
\ [\ LN F (X) = \ int \ FRAC {F '(X)} {F (X)} DX \]
Vector polynomial problems simply do artifact. It resizecan be filled with a zero modulo may be.

#include<bits/stdc++.h>
#define il inline
#define co const
template<class T>T read(){
    T data=0,w=1;char ch=getchar();
    for(;!isdigit(ch);ch=getchar())if(ch=='-') w=-w;
    for(;isdigit(ch);ch=getchar()) data=data*10+ch-'0';
    return data*w;
}
template<class T>il T read(T&x) {return x=read<T>();}
typedef long long LL;
using namespace std;
typedef vector<int> polynomial;

co int mod=998244353,g=3,g_inv=332748118;
il int add(int a,int b){
    return (a+=b)>=mod?a-mod:a;
}
il int mul(int a,int b){
    return (LL)a*b%mod;
}
int fpow(int a,int b){
    int ans=1;
    for(;b;b>>=1,a=mul(a,a))
        if(b&1) ans=mul(ans,a);
    return ans;
}
void num_trans(polynomial&a,int inverse){
    int limit=a.size(),len=log2(limit);
    static vector<int> bit_rev;
    if(bit_rev.size()!=limit){
        bit_rev.resize(limit);
        for(int i=0;i<limit;++i) bit_rev[i]=bit_rev[i>>1]>>1|(i&1)<<(len-1);
    }
    for(int i=0;i<limit;++i)if(i<bit_rev[i]) swap(a[i],a[bit_rev[i]]);
    for(int step=1;step<limit;step<<=1){
        int gn=fpow(inverse==1?g:g_inv,(mod-1)/(step<<1));
        for(int even=0;even<limit;even+=step<<1){
            int odd=even+step,gk=1;
            for(int k=0;k<step;++k,gk=mul(gk,gn)){
                int t=mul(gk,a[odd+k]);
                a[odd+k]=add(a[even+k],mod-t),a[even+k]=add(a[even+k],t);
            }
        }
    }
    if(inverse==-1){
        int lim_inv=fpow(limit,mod-2);
        for(int i=0;i<limit;++i) a[i]=mul(a[i],lim_inv);
    }
}
polynomial poly_inv(polynomial a,int n){ // mod x^n
    polynomial b[2];
    b[0].push_back(fpow(a[0],mod-2));
    if(n==1) return b[0];
    a.resize(1<<int(ceil(log2(n))+1));
    int limit,len;
    for(limit=2,len=1;limit<n;limit<<=1,++len){
        polynomial a1(a.begin(),a.begin()+limit);
        a1.resize(limit<<1),num_trans(a1,1);
        b[(len&1)^1].resize(limit<<1),num_trans(b[(len&1)^1],1);
        b[len&1].resize(limit<<1);
        for(int i=0;i<limit<<1;++i) b[len&1][i]=mul(add(2,mod-mul(a1[i],b[(len&1)^1][i])),b[(len&1)^1][i]);
        num_trans(b[len&1],-1),b[len&1].resize(limit);
    }
    assert(a.size()==limit<<1),num_trans(a,1);
    b[(len&1)^1].resize(limit<<1),num_trans(b[(len&1)^1],1);
    b[len&1].resize(limit<<1);
    for(int i=0;i<limit<<1;++i) b[len&1][i]=mul(add(2,mod-mul(a[i],b[(len&1)^1][i])),b[(len&1)^1][i]);
    num_trans(b[len&1],-1),b[len&1].resize(n);
    return b[len&1];
}
polynomial poly_der(co polynomial&a){
    polynomial b(a.size()-1);
    for(int i=0;i<b.size();++i) b[i]=mul(i+1,a[i+1]);
    return b;
}
polynomial poly_int(co polynomial&a){
    polynomial b(a.size()+1);
    for(int i=1;i<b.size();++i) b[i]=mul(fpow(i,mod-2),a[i-1]);
    return b;
}
polynomial poly_ln(polynomial a,int n){ // mod x^n
    polynomial b=poly_inv(a,n);
    a=poly_der(a);
    int limit=1<<int(ceil(log2(2*n-1)));
    a.resize(limit),b.resize(limit);
    num_trans(a,1),num_trans(b,1);
    for(int i=0;i<limit;++i) a[i]=mul(a[i],b[i]);
    num_trans(a,-1),a.resize(n);
    a=poly_int(a),a.resize(n);
    return a;
}
int main(){
    int n=read<int>();
    polynomial a(n);
    for(int i=0;i<n;++i) read(a[i]);
    polynomial b=poly_ln(a,n);
    for(int i=0;i<n;++i) printf("%d ",b[i]);
    return 0;
}

Guess you like

Origin www.cnblogs.com/autoint/p/11116540.html