• 多项式除法


    多项式除法

    题意

    给定一个 (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;
    }
    
    
  • 相关阅读:
    2017-5-16
    2017-3-6 Develop Engineer 面试
    2017 3-4/5 两天的学习的REVIEW
    2017-3-2 C# WindowsForm 中label标签居中显示
    css图片响应式+垂直水平居中2
    flash上传在spring mvc中出现的问题2
    avalon js实现拖动图片排序
    css图片响应式+垂直水平居中1
    flash上传在spring mvc中出现的问题1
    mybatis Result Maps对结果分组3--一对多使用limit
  • 原文地址:https://www.cnblogs.com/mrasd/p/9509262.html
Copyright © 2020-2023  润新知