多项式求逆

\[A\times B\equiv 1(\mod x^n)\\ A\times B'\equiv 1(\mod x^{\frac n 2}) \]

那么

\[B-B'\equiv0(\mod x^{\frac n 2})\\ (B-B')^2\equiv0 (\mod x^n)\\ B^2-2BB'+B'^2\equiv0(\mod x^n) \]

同乘 \(A\),得

\[AB^2-2ABB'+AB'^2\equiv0(\mod x^n)\\ B-2B'+AB'^2\equiv0(\mod x^n)\\ B\equiv B'(2-AB')(\mod x^n) \]

Code

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
inline ll poww(ll x,int k,int mod)
{
	ll res=1;
	while(k)
	{
		if(k&1) res=1ll*res*x%mod;
		x=x*x%mod;
		k>>=1;
	}
	return res;
}
const int mod=998244353,G=3,invG=poww(G,mod-2,mod),N=(1e5+9)*20;
ll f[N],g[N],t[N];
int n,r[N],lim,len;

inline void NTT(ll *f,int lim,int op)
{
	for(int i=0;i<lim;i++) if(i<r[i]) swap(f[i],f[r[i]]);
	for(int mid=1;mid<lim;mid<<=1)
	{
		ll Wn=poww(op==1?G:invG,(mod-1)/(mid<<1),mod);
		for(int i=0;i<lim;i+=(mid<<1))
		{
			ll w=1;
			for(int k=0;k<mid;k++,w=(w*Wn)%mod)
			{
				ll x=f[i+k],y=f[i+k+mid]*w%mod;
				f[i+k]=(x+y)%mod;
				f[i+k+mid]=(x-y+mod)%mod;
			}
		}
	}
	if(op==1) return;
	ll inv=poww(lim,mod-2,mod);
	for(int i=0;i<lim;i++)
		f[i]=f[i]*inv%mod;
}

void solve(ll *f,ll *g,int len)
{
	if(len==1){g[0]=poww(f[0],mod-2,mod);return;}
	solve(f,g,(len+1)>>1);
	int l=0,lim=1;
	while(lim<(len<<1)) lim<<=1,++l;
	for(int i=0;i<lim;i++) r[i]=(r[i>>1]>>1)|((i&1)<<(l-1));
	memset(t,0,sizeof t);
	for(int i=0;i<len;i++) t[i]=f[i];
	NTT(t,lim,1),NTT(g,lim,1);
	for(int i=0;i<lim;i++) g[i]=(2ll-t[i]*g[i]%mod+mod)%mod*g[i]%mod;
	NTT(g,lim,-1);
	for(int i=len;i<lim;i++) g[i]=0;
}

int main()
{
	scanf("%d",&n);
	for(int i=0;i<n;i++) scanf("%lld",&f[i]);
	solve(f,g,n); 
	for(int i=0;i< n;i++) printf("%lld ",g[i]);
	return 0;
}
原文地址:https://www.cnblogs.com/Alansp/p/13729276.html