多项式乘法逆学习笔记

文章目录

问题

现在有一个给定的 n − 1 n-1 n1 次多项式 F ( x ) F(x) F(x) ,求解 n − 1 n-1 n1 多项式 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)F1(x) (mod xn),其中 F ( x ) F − 1 ( x ) = 1 F(x)F^{-1}(x)=1 F(x)F1(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 2n1 次项系数都为零,则 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) g0f01f0998244351 (mod 998244353),求一遍乘法逆元即可。
时间复杂度分析
倍增复杂度为 O ( log ⁡ 2 n ) O(\log_2n) O(log2n),乘法可以采用 FFTNTT。如果令 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=0mi2i)<O(mi=0m2i)<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;
}

谢谢观看,记得点赞

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值