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
6 1 927384623 878326372 3882 273455637 998233543
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 resize
can 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;
}