背景:
多项式全家桶
eating...
\text{eating...}
eating...
题目传送门:
https://www.luogu.org/problemnew/show/P4726
题意:
求一个多项式 G ( x ) G(x) G(x),使得 G ( x ) ≡ e F ( x ) ( m o d    x n ) G(x)≡e^{F(x)} (\mod x^n) G(x)≡eF(x)(modxn)。
思路:
大力推式子。
G
(
x
)
≡
e
F
(
x
)
(
m
o
d
  
x
n
)
G(x)≡e^{F(x)}(\mod x^n)
G(x)≡eF(x)(modxn)
两边同时取对数,得:
lg
G
(
x
)
≡
F
(
x
)
(
m
o
d
  
x
n
)
lg
G
(
x
)
−
F
(
x
)
≡
0
(
m
o
d
  
x
n
)
\begin{aligned}\lg G(x)&≡F(x)(\mod x^n)\\ \lg G(x)-F(x)&≡0(\mod x^n)\end{aligned}
lgG(x)lgG(x)−F(x)≡F(x)(modxn)≡0(modxn)
考虑牛顿迭代解决问题,假设做完前
n
n
n项的结果为
H
(
x
)
H(x)
H(x),即:
G
(
x
)
≡
H
(
x
)
(
m
o
d
  
x
n
)
G(x)≡H(x)(\mod x^n)
G(x)≡H(x)(modxn)
设
f
(
G
(
x
)
)
=
lg
G
(
x
)
−
F
(
x
)
f\big(G(x)\big)=\lg G(x)-F(x)
f(G(x))=lgG(x)−F(x),则有:
f
(
G
(
x
)
)
≡
0
(
m
o
d
  
x
n
)
f\big(G(x)\big)≡0(\mod x^n)
f(G(x))≡0(modxn)
做泰勒展开,有:
f
(
H
(
x
)
)
+
f
′
(
H
(
x
)
)
(
G
(
x
)
−
H
(
x
)
)
+
f
′
′
(
H
(
x
)
)
(
G
(
x
)
−
H
(
x
)
)
2
2
+
.
.
.
≡
0
(
m
o
d
  
x
n
)
f
(
H
(
x
)
)
+
f
′
(
H
(
x
)
)
(
G
(
x
)
−
H
(
x
)
)
≡
0
(
m
o
d
  
x
2
n
)
\begin{aligned}f\big(H(x)\big)+f'\big(H(x)\big)\big(G(x)-H(x)\big)+\frac{f''\big(H(x)\big)\big(G(x)-H(x)\big)^2}{2}+...&≡0(\mod x^n)\\ f\big(H(x)\big)+f'\big(H(x)\big)\big(G(x)-H(x)\big)&≡0(\mod x^{2n})\end{aligned}
f(H(x))+f′(H(x))(G(x)−H(x))+2f′′(H(x))(G(x)−H(x))2+...f(H(x))+f′(H(x))(G(x)−H(x))≡0(modxn)≡0(modx2n)
移项得:
G
(
x
)
≡
H
(
x
)
−
f
(
H
(
x
)
)
f
′
(
H
(
x
)
)
(
m
o
d
  
x
2
n
)
G(x)≡H(x)-\frac{f\big(H(x)\big)}{f'\big(H(x)\big)}(\mod x^{2n})
G(x)≡H(x)−f′(H(x))f(H(x))(modx2n)
带入
f
(
G
(
x
)
)
=
lg
G
(
x
)
−
F
(
x
)
f\big(G(x)\big)=\lg G(x)-F(x)
f(G(x))=lgG(x)−F(x),有:
G
(
x
)
≡
H
(
x
)
−
ln
H
(
x
)
−
F
(
x
)
1
H
(
x
)
(
m
o
d
  
x
2
n
)
G
(
x
)
≡
H
(
x
)
(
1
−
ln
H
(
x
)
+
F
(
x
)
)
(
m
o
d
  
x
2
n
)
\begin{aligned}G(x)&≡H(x)-\frac{\ln H(x)-F(x)}{\frac{1}{H(x)}}(\mod x^{2n})\\ G(x)&≡H(x)\big(1-\ln H(x)+F(x)\big)(\mod x^{2n})\end{aligned}
G(x)G(x)≡H(x)−H(x)1lnH(x)−F(x)(modx2n)≡H(x)(1−lnH(x)+F(x))(modx2n)
递归倍增解决即可。
注意上面的
1
1
1是点乘的
1
1
1,要在常数项赋值为
1
1
1。
多项式求
ln
\ln
ln之后的结果
g
2
g2
g2要在每一次
exp
\text{exp}
exp时清空。
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long
const LL mod=998244353,G=3,inv_G=332748118;
using namespace std;
LL a[1000010],b[1000010],f[1000010],g[1000010],g1[1000010],g2[1000010];
int limit,n,l,r[1000010];
LL dg(LL x,LL k)
{
if(!k) return 1;
LL op=dg(x,k>>1);
if(k&1) return op*op%mod*x%mod; else return op*op%mod;
}
LL inv(LL x)
{
return dg(x,mod-2);
}
void dao(LL *f,LL *g,int n)
{
for(int i=1;i<n;i++)
g[i-1]=i*f[i]%mod;
g[n-1]=0;
}
void jifen(LL *f,LL *g,int n)
{
for(int i=1;i<n;i++)
g[i]=f[i-1]*inv(i)%mod;
g[0]=0;
}
void init(int n)
{
limit=1,l=0;
while(limit<(n<<1))
limit<<=1,l++;
for(int i=1;i<limit;i++)
r[i]=((r[i>>1]>>1)|((i&1)<<(l-1)));
}
void NTT(LL *now,int limit,int op)
{
for(int i=0;i<limit;i++)
if(i<r[i]) swap(now[i],now[r[i]]);
for(int mid=1;mid<limit;mid<<=1)
{
LL wn=dg(op==1?G:inv_G,(mod-1)/(mid<<1));
for(int j=0;j<limit;j+=(mid<<1))
{
LL w=1;
for(int k=0;k<mid;k++,w=(w*wn)%mod)
{
LL x=now[j+k],y=w*now[j+k+mid]%mod;
now[j+k]=(x+y)%mod;
now[j+k+mid]=(x-y+mod)%mod;
}
}
}
}
void dft(LL *f,int n,int limit)
{
NTT(f,limit,-1);
LL INV=inv(limit);
for(int i=0;i<n;i++)
f[i]=f[i]*INV%mod;
}
void poly_inv(LL *f,LL *g,int n)
{
if(n==1)
{
g[0]=inv(f[0]);
return;
}
poly_inv(f,g,(n+1)>>1);
init(n);
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
for(int i=0;i<n;i++)
a[i]=f[i],b[i]=g[i];
NTT(a,limit,1),NTT(b,limit,1);
for(int i=0;i<limit;i++)
b[i]=b[i]*((2ll-a[i]*b[i]%mod+mod)%mod)%mod;
dft(b,n,limit);
for(int i=0;i<n;i++)
g[i]=b[i];
}
void poly_ln(LL *f,int n)
{
dao(f,g1,n);
poly_inv(f,g2,n);
init(n);
NTT(g1,limit,1),NTT(g2,limit,1);
for(int i=0;i<limit;i++)
g1[i]=g1[i]*g2[i]%mod;
dft(g1,n,limit);
jifen(g1,g2,n);
}
void poly_exp(LL *f,LL *g,int n)
{
if(n==1)
{
g[0]=1;
return;
}
poly_exp(f,g,(n+1)>>1);
memset(g1,0,sizeof(g1));
memset(g2,0,sizeof(g2));
poly_ln(g,n);
init(n);
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
for(int i=0;i<n;i++)
a[i]=g[i],b[i]=((LL)(!i)-g2[i]+f[i]+mod)%mod;
NTT(a,limit,1),NTT(b,limit,1);
for(int i=0;i<limit;i++)
a[i]=a[i]*b[i]%mod;
dft(a,n,limit);
for(int i=0;i<n;i++)
g[i]=a[i];
}
int main()
{
scanf("%d",&n);
for(int i=0;i<n;i++)
scanf("%lld",&f[i]);
poly_exp(f,g,n);
for(int i=0;i<n;i++)
printf("%lld ",g[i]);
}