背景:
多项式全家桶
eating...
\text{eating...}
eating...
题目传送门:
https://www.luogu.org/problemnew/show/P4512
题意:
给定多项式
F
(
x
)
,
G
(
x
)
F(x),G(x)
F(x),G(x),分别为
n
,
m
n,m
n,m次,求两个多项式
Q
(
x
)
,
R
(
x
)
Q(x),R(x)
Q(x),R(x),分别为
n
−
m
,
m
−
1
n-m,m-1
n−m,m−1次,使得
F
(
x
)
=
Q
(
x
)
∗
G
(
x
)
+
R
(
x
)
F(x)=Q(x)*G(x)+R(x)
F(x)=Q(x)∗G(x)+R(x)。
思路:
F ( x ) = Q ( x ) ∗ G ( x ) + R ( x ) F(x)=Q(x)*G(x)+R(x) F(x)=Q(x)∗G(x)+R(x)
带入
x
=
1
x
x=\frac{1}{x}
x=x1(并不是真正意义上的等于,只是代表),得:
F
(
1
x
)
=
Q
(
1
x
)
∗
G
(
1
x
)
+
R
(
1
x
)
F(\frac{1}{x})=Q(\frac{1}{x})*G(\frac{1}{x})+R(\frac{1}{x})
F(x1)=Q(x1)∗G(x1)+R(x1)
左右两边同时乘
x
n
x^n
xn,得:
x
n
F
(
1
x
)
=
x
n
(
Q
(
1
x
)
∗
G
(
1
x
)
+
R
(
1
x
)
)
x
n
F
(
1
x
)
=
x
n
−
m
Q
(
1
x
)
∗
x
m
G
(
1
x
)
+
x
n
−
m
+
1
⋅
x
m
−
1
R
(
1
x
)
\begin{aligned}x^nF(\frac{1}{x})&=x^n\big(Q(\frac{1}{x})*G(\frac{1}{x})+R(\frac{1}{x})\big)\\ x^nF(\frac{1}{x})&=x^{n-m}Q(\frac{1}{x})*x^mG(\frac{1}{x})+x^{n-m+1}\cdot x^{m-1}R(\frac{1}{x}\big)\end{aligned}
xnF(x1)xnF(x1)=xn(Q(x1)∗G(x1)+R(x1))=xn−mQ(x1)∗xmG(x1)+xn−m+1⋅xm−1R(x1)
我们使其系数翻转的结果视为
F
R
,
Q
R
,
G
R
,
R
R
F_R,Q_R,G_R,R_R
FR,QR,GR,RR,也就是说
F
R
=
x
n
F
(
1
x
)
F_R=x^nF(\frac{1}{x})
FR=xnF(x1),有:
F
R
=
Q
R
∗
G
R
+
x
n
−
m
+
1
R
R
F
R
≡
Q
R
∗
G
R
+
x
n
−
m
+
1
R
R
(
m
o
d
  
x
n
−
m
+
1
)
F
R
≡
Q
R
∗
G
R
(
m
o
d
  
x
n
−
m
+
1
)
Q
R
≡
F
R
G
R
(
m
o
d
  
x
n
−
m
+
1
)
\begin{aligned}F_R&=Q_R*G_R+x^{n-m+1}R_R\\ F_R&≡Q_R*G_R+x^{n-m+1}R_R(\mod x^{n-m+1})\\ F_R&≡Q_R*G_R(\mod x^{n-m+1})\\ Q_R&≡\frac{F_R}{G_R}(\mod x^{n-m+1})\end{aligned}
FRFRFRQR=QR∗GR+xn−m+1RR≡QR∗GR+xn−m+1RR(modxn−m+1)≡QR∗GR(modxn−m+1)≡GRFR(modxn−m+1)
系数反转后,得到
F
R
,
G
R
F_R,G_R
FR,GR,套一个多项式求逆,卷一下,便可搞定
Q
R
Q_R
QR,系数反转后得到
Q
Q
Q,套回
R
(
x
)
=
F
(
x
)
−
Q
(
x
)
∗
G
(
x
)
R(x)=F(x)-Q(x)*G(x)
R(x)=F(x)−Q(x)∗G(x),即可。
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long
const LL mod=998244353,G=3,inv_G=332748118;
using namespace std;
int a[1000010],b[1000010],f[1000010],g[1000010],q[1000010],fr[1000010],gr[1000010],qr[1000010],grr[1000010];
int limit,n,m,l,r[1000010];
int dg(int x,int k)
{
if(!k) return 1;
int op=dg(x,k>>1);
if(k&1) return (LL)op*op%mod*x%mod; else return (LL)op*op%mod;
}
int inv(int x)
{
return dg(x,mod-2);
}
void init(int n)
{
limit=1,l=0;
while(limit<(n<<1))
limit<<=1,l++;
for(int i=1;i<limit;i++)
r[i]=((r[i>>1]>>1)|((i&1)<<(l-1)));
}
void NTT(int *now,int limit,int op)
{
for(int i=0;i<limit;i++)
if(i<r[i]) swap(now[i],now[r[i]]);
for(int mid=1;mid<limit;mid<<=1)
{
int wn=dg(op==1?G:inv_G,(mod-1)/(mid<<1));
for(int j=0;j<limit;j+=(mid<<1))
{
int w=1;
for(int k=0;k<mid;k++,w=((LL)w*wn)%mod)
{
int x=now[j+k],y=(LL)w*now[j+k+mid]%mod;
now[j+k]=(x+y)%mod;
now[j+k+mid]=(x-y+mod)%mod;
}
}
}
}
void dft(int *f,int n,int limit)
{
NTT(f,limit,-1);
int INV=inv(limit);
for(int i=0;i<n;i++)
f[i]=(LL)f[i]*INV%mod;
}
void poly_inv(int *f,int *g,int n)
{
if(n==1)
{
g[0]=inv(f[0]);
return;
}
poly_inv(f,g,(n+1)>>1);
init(n);
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
for(int i=0;i<n;i++)
a[i]=f[i],b[i]=g[i];
NTT(a,limit,1),NTT(b,limit,1);
for(int i=0;i<limit;i++)
b[i]=(LL)b[i]*((2ll-(LL)a[i]*b[i]%mod+mod)%mod)%mod;
dft(b,n,limit);
for(int i=0;i<n;i++)
g[i]=b[i];
}
void poly_chu(int *f,int *g,int n,int m)
{
for(int i=0;i<=n;i++)
fr[i]=f[n-i];
for(int i=0;i<=m;i++)
gr[i]=g[m-i];
poly_inv(gr,grr,n-m+1);
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
init((n-m)+(n-m));
for(int i=0;i<=n-m;i++)
a[i]=fr[i];
for(int i=0;i<=n-m;i++)
b[i]=grr[i];
NTT(a,limit,1),NTT(b,limit,1);
for(int i=0;i<limit;i++)
a[i]=(LL)a[i]*b[i]%mod;
dft(a,n-m+1,limit);
for(int i=0;i<=n-m;i++)
q[i]=a[n-m-i];
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
init(n-m+m+1);
for(int i=0;i<=n-m;i++)
a[i]=q[i];
for(int i=0;i<=m;i++)
b[i]=g[i];
NTT(a,limit,1),NTT(b,limit,1);
for(int i=0;i<limit;i++)
a[i]=(LL)a[i]*b[i]%mod;
dft(a,m,limit);
for(int i=0;i<m;i++)
r[i]=(f[i]-a[i]+mod)%mod;
}
int main()
{
scanf("%d %d",&n,&m);
for(int i=0;i<=n;i++)
scanf("%d",&f[i]);
for(int i=0;i<=m;i++)
scanf("%d",&g[i]);
poly_chu(f,g,n,m);
for(int i=0;i<=n-m;i++)
printf("%d ",q[i]);
printf("\n");
for(int i=0;i<m;i++)
printf("%d ",r[i]);
}