看到成爷爷写了一篇就跟风写一篇吧,慢慢更
1.多项式求逆
就是给定多项式\(F(x)\),求一个多项式\(G(x)\)
使得
\[F(x)\times G(x)\equiv 1(mod\ x^n)\]
\(mod\ x^n\)就是只考虑前\(n\)项
这是一个基于倍增的算法,就是推一下如何从\(mod\ x^{\frac{n}{2}}\)推到\(mod\ x^n\)
设多项式\(B'(x)\)满足
\[F(x)B'(x)\equiv 1(mod\ x^{\frac{n}{2}})\]
求多项式\(B(x)\)满足
\[F(x)B(x)\equiv 1(mod\ x^{n})\]
后面那个忽略前\(n\)项,所以前\(\frac{n}{2}\)项肯定会满足
\[F(x)B(x)\equiv 1(mod\ x^{\frac{n}{2}})\]
和第一个柿子一减
\[F(B-B')\equiv 0(mod\ x^{\frac{n}{2}})\]
显然\(F\)不可能是\(0\),于是只能是\((B-B')=0\)
于是
\[B-B'\equiv 0 (mod\ x^{\frac{n}{2}})\]
两边平方并且乘上\(F\)
\[F(B-B')^2\equiv 0(mod\ x^n)\]
\[F\times B^2-F\times 2BB'+F\times B'^2\equiv 0(mod\ x^n)\]
别忘了\(F(x)B(x)\equiv 1(mod\ x^{\frac{n}{2}})\)就有
\[B-2B'+FB'^2\equiv 0(mod\ x^n)\]
\[B\equiv 2B'-FB'^2(mod\ x^n)\]
发现这个东西可以倍增来求,就是需要一个\(NTT\)了
时间复杂度\(T(n)=T(n/2)+O(nlogn)=O(nlogn)\)
代码
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#define maxn 300005
#define re register
#define LL long long
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
inline int read() {
char c=getchar();int x=0;while(c<'0'||c>'9') c=getchar();
while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar();return x;
}
const LL mod=998244353;
const LL g[2]={332748118,3};
int n,rev[maxn],len;
LL a[maxn],b[maxn],C[maxn];
inline LL quick(LL a,LL b) {LL S=1;while(b) {if(b&1ll) S=S*a%mod;b>>=1ll;a=a*a%mod;}return S;}
inline void NTT(LL *f,int o) {
for(re int i=0;i<len;i++) if(i<rev[i]) std::swap(f[i],f[rev[i]]);
for(re int i=2;i<=len;i<<=1) {
int ln=i>>1;LL og1=quick(g[o],(mod-1)/i);
for(re int l=0;l<len;l+=i) {
LL og=1,t;
for(re int x=l;x<l+ln;x++) {
t=(og*f[ln+x])%mod;
f[ln+x]=(f[x]-t+mod)%mod;
f[x]=(f[x]+t)%mod;
og=(og*og1)%mod;
}
}
}
if(o) return;
LL inv=quick(len,mod-2);
for(re int i=0;i<len;i++) f[i]=(f[i]*inv)%mod;
}
inline void Inv(int n,LL *A,LL *B) {
if(n==1) {B[0]=quick(A[0],mod-2);return;}
Inv((n+1)>>1,A,B);len=1;
while(len<=n+n-2) len<<=1;
for(re int i=0;i<n;i++) C[i]=A[i];
for(re int i=n;i<len;i++) C[i]=0;
for(re int i=0;i<len;i++) rev[i]=(rev[i>>1]>>1)|((i&1)?len>>1:0);
NTT(C,1),NTT(B,1);
for(re int i=0;i<len;i++) B[i]=(2ll*B[i]%mod-C[i]*B[i]%mod*B[i]+mod)%mod,B[i]=(B[i]+mod)%mod;
NTT(B,0);for(re int i=n;i<len;i++) B[i]=0;
}
int main()
{
n=read();
for(re int i=0;i<n;i++) a[i]=read();
Inv(n,a,b);
for(re int i=0;i<n;i++) printf("%lld ",b[i]);
return 0;
}