Luogu4238 【模板】多项式乘法逆
https://www.luogu.com.cn/problem/P4238
\(NTT\)
递归求解
\[假设已知F(n)H(n) \equiv 1 (\mod x^{\lceil \frac{n}{2} \rceil} )\\
F(n)G(n)\equiv 1 (\mod x^{\lceil \frac{n}{2} \rceil})\\
\therefore F(n)(G(n)-H(n)) \equiv 0 (\mod x^{\lceil \frac{n}{2} \rceil} )\\
G(n)-H(n) \equiv 0 (\mod x^{\lceil \frac{n}{2} \rceil })\\
令P(n)=G(n)-H(n),C(n)=P(n)^2\\
C_{i}=\sum_{j=0}^i P_j *P_{i-j}\\
j和i-j中,必然有一项值小于等于\lceil \frac{n}{2} \rceil\\
那么P_i和P_{i-j}中必有一项为0(\because P(n) \equiv 0 (\mod x^{\lceil \frac{n}{2} \rceil}))\\
\therefore C(n) \equiv 0 (\mod x^n)\\
(G(n)-H(n))^2 \equiv 0 (\mod x^n)\\
G(n)^2-2G(n)H(n)+H(n)^2 \equiv 0 (\mod x^n)\\
F(n)G(n)^2-2F(n)G(n)H(n)+F(n)H(n)^2 \equiv 0 (\mod x^n)\\
G(n)\equiv 2H(n)-F(n)H(n)^2 (\mod x^n)
\]
\(C++ Code:\)
#include<iostream>
#include<cstdio>
#include<algorithm>
#define p 998244353
#define Gi 3
#define N 400005
#define ll long long
using namespace std;
int n,l,lg2[N << 2],rev[N << 2];
ll G[2][24],s,f[N],g[N],a[N],b[N];
inline ll ksm(ll x,ll y)
{
ll ans=1;
while (y)
{
if (y & 1)
ans=ans*x%p;
x=x*x%p;
y >>=1;
}
return ans;
}
#define inv(x) (ksm(x,p-2))
inline void NTT(ll *a,int t)
{
for (int i=0;i<s;i++)
if (i<rev[i])
swap(a[i],a[rev[i]]);
for (int mid=1,o=1;mid<s;mid <<=1,o++)
{
ll gn=G[t][o];
for (int j=0;j<s;j+=(mid << 1))
{
ll g=1;
for (int k=0;k<mid;k++,g=g*gn%p)
{
ll x=a[j+k],y=g*a[j+k+mid]%p;
a[j+k]=(x+y)%p;
a[j+k+mid]=(x-y)%p;
}
}
}
}
void dfs(int l,int r)
{
if (l==r)
{
g[l]=inv(f[l]);
return;
}
int mid=(l+r) >> 1;
dfs(l,mid);
s=1 << (lg2[r-l+1]+1);
for (int i=0;i<s;i++)
rev[i]=(rev[i >> 1] >> 1) | ( (i & 1) << lg2[r-l+1] );
for (int i=l;i<=mid;i++)
a[i]=g[i];
for (int i=mid+1;i<s;i++)
a[i]=0;
for (int i=l;i<=r;i++)
b[i]=f[i];
for (int i=r+1;i<s;i++)
b[i]=0;
NTT(a,0);
NTT(b,0);
for (int i=0;i<s;i++)
a[i]=a[i]*a[i]%p*b[i]%p;
NTT(a,1);
ll t=inv(s);
for (int i=0;i<s;i++)
a[i]=a[i]*t%p;
for (int i=0;i<r-l+1;i++)
g[i]=(g[i]*2-a[i])%p;
}
void Pre()
{
G[0][23]=ksm(3,(p-1)/(1 << 23));
G[1][23]=inv(G[0][23]);
for (int i=22;i>=1;i--)
{
G[0][i]=G[0][i+1]*G[0][i+1]%p;
G[1][i]=G[1][i+1]*G[1][i+1]%p;
}
}
int main()
{
Pre();
scanf("%d",&n);
for (int i=0;i<n;i++)
scanf("%lld",&f[i]);
lg2[0]=0;
l=0;
for (int i=1;i<=n;i++)
{
if ((1 << l)<i)
l++;
lg2[i]=l;
}
for (int i=n+1;i<=(1 << lg2[n]);i++)
lg2[i]=lg2[n];
dfs(0,(1 << lg2[n])-1);
for (int i=0;i<n;i++)
g[i]=(g[i]%p+p)%p;
for (int i=0;i<n;i++)
printf("%lld ",g[i]);
putchar('\n');
return 0;
}