多项式除法
多项式除法
题意
给定一个 \(n\) 次多项式 \(F(x)\) 和一个$ m$ 次多项式 \(G(x)\) ,请求出多项式 \(Q(x)\) , \(R(x)\) ,满足以下条件:
\(Q(x)\) 次数为 \(n-m\) , \(R(x)\) 次数小于$ m\(
\)F(x) = Q(x) * G(x) + R(x)$
所有的运算在模 \(998244353\) 意义下进行。
解法
我们假设一个变换:
$ A_R( x ) = x^n A( \frac{1}{x})$
然后我们可以发现 \(A_R\) 与 \(A\) 的系数翻转了过来。
于是我们对原式进行变换有:
\(F( \frac{1}{x} ) = Q( \frac{1}{x} ) * G( \frac{1}{x} ) + R( \frac{1}{x} )\)
\(x^n F( \frac{1}{x} ) = x^{n-m} Q( \frac{1}{x} ) * x^m G( \frac{1}{x} ) + x^{n-m+1} R( \frac{1}{x} )\)
\(F_R(x) = Q_R(x) * G_R(x) + x^{n-m+1} R_R(x)\)
\(F_R(x) = Q_R(x) * G_R(x) (mod x^ {n-m+1})\)
\(F_R(x) * Q_R(x)^{-1} = G_R(x) (mod x^ {n-m+1})\)
然后我们就可以愉快的求出 \(G(x)\) 。
又因为 \(R(x) = F(x) - Q(x) * G(x)\)
所以我们又可以愉快地求出 \(R(x)\) 了。
代码如下:
#include <bits/stdc++.h>
using namespace std;
const int maxn=(1e5+5)*3;
const int mod=998244353;
const int g=3;
int add(int x,int y) {return (x+y)%mod; }
int mul(int x,int y) {return 1ll*x*y%mod; }
int pul(int x,int y) {return (x-y+mod)%mod; }
int poww(int a,int b){
int ans=1;
while(b){
if(b&1) ans=mul(ans,a);
a=mul(a,a);
b>>=1;
}
return ans;
}
int inv(int x) {return poww(x,mod-2); }
void ntt(int n,int f,int *a) {
for(int i=0,j=0;i<n;i++) {
if(i<j) swap(a[i],a[j]);
for(int l=(n>>1);(j^=l)<l;l>>=1);
}
for(int i=1;i<n;i<<=1) {
int gn=poww(g,(mod-1)/(i<<1));
if(f==-1) gn=inv(gn);
for(int j=0;j<n;j+=(i<<1)) {
int g=1;
for(int k=0;k<i;k++,g=mul(g,gn)) {
int x=a[j+k],y=mul(g,a[i+j+k]);
a[j+k]=add(x,y);
a[i+j+k]=pul(x,y);
}
}
}
if(f==-1) {
int ni=inv(n);
for(int i=0;i<n;i++) a[i]=mul(a[i],ni);
}
}
void inv_p(int deg,int *a,int *b,int *temp) {
if(deg==1) {b[0]=inv(a[0]); return;}
inv_p( (deg+1)>>1 ,a,b,temp);
int p=1;
for(;p<=(deg<<1);p<<=1);
copy(a,a+deg,temp);
fill(temp+deg,temp+p,0);
ntt(p,1,temp);
ntt(p,1,b);
for(int i=0;i<p;i++){
b[i] = mul( pul(2,mul(temp[i],b[i])) , b[i]);
}
ntt(p,-1,b);
fill(b+deg,b+p,0);
}
int A[maxn],B[maxn],temp[maxn];
void div_p(int n,int m,int *a,int *b,int *D,int *R) {
int deg=n-m+1;
int p=1;
for(;p<=(deg*2);p<<=1);
reverse_copy(b,b+m,A);
fill(A+deg,A+p,0);
inv_p(deg,A,B,temp);
ntt(p,1,B);
reverse_copy(a,a+n,A);
fill(A+deg,A+p,0);
ntt(p,1,A);
for(int i=0;i<p;i++) A[i]=mul(A[i],B[i]);
ntt(p,-1,A);
reverse(A,A+deg);
copy(A,A+deg,D);
for(p=1;p<=n;p<<=1);
fill(A+deg,A+p,0);
ntt(p,1,A);
copy(b,b+m,B);
fill(B+m,B+p,0);
ntt(p,1,B);
for(int i=0;i<p;i++) {
A[i] = mul(A[i],B[i]);
}
ntt(p,-1,A);
for(int i=0;i<m;i++) R[i]=pul(a[i],A[i]);
fill(R+m,R+p,0);
}
int n,m;
int a[maxn],b[maxn],D[maxn],R[maxn];
int main(){
scanf("%d%d",&n,&m);n++,m++;
for(int i=0;i<n;i++) scanf("%d",&a[i]);
for(int i=0;i<m;i++) scanf("%d",&b[i]);
div_p(n,m,a,b,D,R);
n--,m--;
for(int i=0;i<n-m+1;i++) printf("%d ",D[i]);
puts("");
for(int i=0;i<m;i++) printf("%d ",R[i]);
return 0;
}