多项式除法

多项式除法

题意

给定一个 \(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;
}

posted @ 2018-08-21 08:34  Mr_asd  阅读(775)  评论(0编辑  收藏  举报