问题
现在有一个给定的 n − 1 n-1 n−1 次多项式 F ( x ) F(x) F(x) ,求解 n − 1 n-1 n−1 多项式 G ( x ) G(x) G(x),使得 G ( x ) ≡ F − 1 ( x ) ( mod x n ) G(x)\equiv F^{-1}(x)\ (\text{mod}\ x^n) G(x)≡F−1(x) (mod xn),其中 F ( x ) F − 1 ( x ) = 1 F(x)F^{-1}(x)=1 F(x)F−1(x)=1,系数对 998244353 998244353 998244353 取模。
方法
我们可以采用倍增法求解
递推过程
现在假设已经求出了
G
(
x
)
G(x)
G(x) 的前
n
n
n 项,要求它的前
2
n
2n
2n 项。不妨设有一个多项式
H
(
x
)
H(x)
H(x),它的前
n
n
n 项与
G
(
x
)
G(x)
G(x) 的前
n
n
n 项一致,后
n
n
n 项都为
0
0
0,则有
G
(
x
)
−
H
(
x
)
≡
0
(
mod
x
n
)
G(x)-H(x)\equiv0\ (\text{mod}\ x^n)
G(x)−H(x)≡0 (mod xn)将上式平方,注意到结果的
n
n
n 到
2
n
−
1
2n-1
2n−1 次项系数都为零,则
G
2
(
x
)
−
2
G
(
x
)
H
(
x
)
+
H
2
(
X
)
≡
0
(
mod
x
2
n
)
G^2(x)-2G(x)H(x)+H^2(X)\equiv0\ (\text{mod}\ x^{2n})
G2(x)−2G(x)H(x)+H2(X)≡0 (mod x2n)
再把两端同时乘上
F
(
x
)
F(x)
F(x),即可得到
F
(
x
)
[
G
2
(
x
)
−
2
G
(
x
)
H
(
x
)
+
H
2
(
x
)
]
≡
0
(
mod
x
2
n
)
F(x)[G^2(x)-2G(x)H(x)+H^2(x)]\equiv0\ (\text{mod}\ x^{2n})
F(x)[G2(x)−2G(x)H(x)+H2(x)]≡0 (mod x2n)
注意到
F
(
x
)
G
(
x
)
≡
1
(
mod
x
2
n
)
F(x)G(x)\equiv1\ (\text{mod}\ x^{2n})
F(x)G(x)≡1 (mod x2n),代入上式则有
G
(
x
)
−
2
H
(
x
)
+
F
(
x
)
H
2
(
x
)
≡
0
(
mod
x
2
n
)
G(x)-2H(x)+F(x)H^2(x)\equiv0\ (\text{mod}\ x^{2n})
G(x)−2H(x)+F(x)H2(x)≡0 (mod x2n)
移项后就可以得到递推公式
G
(
x
)
≡
2
H
(
x
)
−
F
(
x
)
H
2
(
x
)
(
mod
x
2
n
)
G(x)\equiv2H(x)-F(x)H^2(x)\ (\text{mod}\ x^{2n})
G(x)≡2H(x)−F(x)H2(x) (mod x2n)
上式表明每次只需要更新
G
(
x
)
=
2
G
(
x
)
−
F
(
x
)
H
2
(
x
)
G(x)=2G(x)-F(x)H^2(x)
G(x)=2G(x)−F(x)H2(x) 再把前
2
n
2n
2n 项保留就行了。
边界条件
常数项时,根据费马小定理,显然有
g
0
≡
f
0
−
1
≡
f
0
998244351
(
mod
998244353
)
g_0\equiv f_0^{-1}\equiv f_0^{998244351}\ (\text{mod}\ 998244353)
g0≡f0−1≡f0998244351 (mod 998244353),求一遍乘法逆元即可。
时间复杂度分析
倍增复杂度为
O
(
log
2
n
)
O(\log_2n)
O(log2n),乘法可以采用 FFT 或 NTT。如果令
m
=
log
2
n
m=\log_2n
m=log2n 复杂度为
O
(
n
log
2
n
)
O(n\log_2n)
O(nlog2n),总复杂度为
O
(
∑
i
=
0
m
i
2
i
)
<
O
(
m
∑
i
=
0
m
2
i
)
<
O
(
2
m
2
m
)
=
O
(
n
log
2
n
)
O(\sum_{i=0}^{m}i2^i)<O(m\sum_{i=0}^m2^i)<O(2m2^m)=O(n\log_2n)
O(i=0∑mi2i)<O(mi=0∑m2i)<O(2m2m)=O(nlog2n)
注意事项
式子中
F
(
x
)
H
2
(
x
)
F(x)H^2(x)
F(x)H2(x) 最高有
3
n
3n
3n 次项,因此要把多项式的长度设为原来的
4
4
4 倍才可以进行 FFT 或 NTT。
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#define ll long long
using namespace std;
ll mod=998244353,G[2]={332748118,3};
ll A[450001],invA[450001],f[450001],g[450001],inv;
int len,m,rev[450001];
ll qp(ll x,int y){
if(y==0) return 1ll;
if(y==1) return x;
ll res=qp(x,y>>1);
(res*=res)%=mod;
if(y&1) (res*=x)%=mod;
return res;
}
void NTT(ll *a,int flag,int n){
ll w,w_n,x,y;
for(int i=1;i<n;i+=1){
if(i<rev[i]) swap(a[i],a[rev[i]]);
}
for(int i=1;i<n;i<<=1){
w_n=qp(G[flag],(mod-1)/(i<<1));
for(int j=0;j<n;j+=(i<<1)){
w=1ll;
for(int k=j;k<i+j;k+=1){
x=a[k]; y=(a[k+i]*w)%mod;
a[k]=(x+y)%mod;
a[k+i]=(x-y+mod)%mod;
(w*=w_n)%=mod;
}
}
}
if(!flag){
inv=qp(n,mod-2);
for(int i=0;i<n;i+=1) (a[i]*=inv)%=mod;
}
return;
}
int main(){
scanf("%d",&len); len-=1;
for(int i=0;i<=len;i+=1) scanf("%lld",&A[i]);
invA[0]=qp(A[0],mod-2); //求解常数项
for(int i=1;i<=len;i<<=1){
memset(g,0,sizeof(g)); m+=1;
for(int j=0;j<i;j+=1) g[j]=invA[j];
for(int j=0;j<(i<<1);j+=1) f[j]=A[j];
for(int j=1;j<(i<<2);j+=1) rev[j]=((rev[j>>1]>>1)|((j&1)<<m));
NTT(g,1,i<<2); NTT(f,1,i<<2);
for(int j=0;j<(i<<2);j+=1) g[j]=(((g[j]*g[j])%mod)*f[j])%mod; //F*G^2
NTT(g,0,i<<2);
for(int j=i;j<(i<<1);j+=1) invA[j]=((invA[j]<<1)%mod-g[j]+mod)%mod; //2G-F*G^2
}
for(int i=0;i<=len;i+=1) printf("%lld ",invA[i]);
printf("\n");
return 0;
}
谢谢观看,记得点赞