zoukankan      html  css  js  c++  java
  • 【学习笔记】MTT

    用于任意模数多项式乘法。

    题目链接

    我们所得到的数最大是(mod^2*Len,)大概是(10^{23})次方级别。这个时候朴素的(FFT)虽然支持取模但是精度会爆炸。

    考虑将原来的多项式(F(x))分解成(A(x)M+B(x).)这样可以使得这两个多项式的系数不至于过大。

    (A[i]=F[i]/M,B[i]=F[i]mod M.)

    这样,(F(x)*G(x)=(A_0(x)M+B_0(x))(A_1(x)M+B_1(x))=A_0A_1(x)M^2+A_0B_1(x)+A_1B_0(x)+B_1B_0(x))

    最后将四个多项式加起来即可。一共需要八次(FFT.)

    #include<bits/stdc++.h>
    using namespace std;
    typedef long double D;
    typedef long long ll;
    inline int MAX(int x,int y){return x>y?x:y;}
    const D Pi=acos(-1.0);
    inline int read() {
    	int f=1, r=0; char c=getchar();
    	while(!isdigit(c)) { if(c=='-')f=-1; c=getchar(); }
    	while(isdigit(c)) { r=r*10+c-'0'; c=getchar(); }
    	return f*r;
    }
    const int MAXN=6e5+10;
    struct cp{
    	D x,y;
    	cp(D xx=0,D yy=0){x=xx,y=yy;}
    };
    int l,r[MAXN],lt=1,n,m,mod;
    inline int add(int x,int y){return (x+y)%mod;}
    inline int mul(int x,int y){return 1ll*x*y%mod;}
    int F[MAXN],G[MAXN],H[MAXN];
    cp operator+(cp a,cp b){return cp(a.x+b.x,a.y+b.y);}
    cp operator-(cp a,cp b){return cp(a.x-b.x,a.y-b.y);}
    cp operator*(cp a,cp b){return cp(a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x);}
    void FFT(cp *P,int tp){
    	for(int i=0;i<lt;++i)if(i<r[i])swap(P[i],P[r[i]]);
    	for(int i=1;i<lt;i<<=1){
    		cp Wn(cos(Pi/i),tp*sin(Pi/i));
    		for(int j=0;j<lt;j+=(i<<1)){
    			cp w(1,0);
    			for(int k=0;k<i;++k,w=w*Wn){
    				cp x=P[j+k],y=w*P[i+j+k];
    				P[j+k]=x+y;
    				P[i+j+k]=x-y;
    			}
    		}
    	}
    	if(tp==-1){
    		for(int i=0;i<lt;++i)P[i].x/=lt;
    	}
    }
    void MTT(int dg,int *A,int *B,int *C){
    	cp a[MAXN],b[MAXN],c[MAXN],d[MAXN];
    	cp e[MAXN],f[MAXN],g[MAXN],h[MAXN];
    	while(lt<=(dg<<1))lt<<=1,l++;
    	for(int i=0;i<lt;++i)r[i]=(r[i>>1]>>1)|((i&1)<<(l-1));
    	for(int i=0;i<lt;++i){
    		A[i]%=mod;B[i]%=mod;
    		a[i]=A[i]>>15;b[i]=A[i]&0x7fff;
    		c[i]=B[i]>>15;d[i]=B[i]&0x7fff;
    	}
    	FFT(a,1);FFT(b,1);FFT(c,1);FFT(d,1);
    	for(int i=0;i<lt;++i){
    		e[i]=a[i]*c[i];f[i]=b[i]*c[i];
    		g[i]=a[i]*d[i];h[i]=b[i]*d[i];
    	}
    	FFT(e,-1);FFT(f,-1);FFT(g,-1);FFT(h,-1);
    	for(int i=0;i<lt;++i){
    		int A1=(((ll(round(e[i].x))%mod)<<30)%mod);
    		int A2=((ll(round(f[i].x))%mod)<<15)%mod;
    		int A3=((ll(round(g[i].x))%mod)<<15)%mod;
    		int A4=ll(round(h[i].x))%mod;
    		A1=add(A1,A2);A1=add(A1,A3);A1=add(A1,A4);
    		C[i]=A1;
    	}
    }
    int main(){
    	n=read();m=read();mod=read();
    	for(int i=0;i<=n;++i)F[i]=read();
    	for(int i=0;i<=m;++i)G[i]=read();
    	MTT(MAX(n,m),F,G,H);
    	for(int i=0;i<=n+m;++i)printf("%d ",H[i]);
    	return 0;
    } 
    
  • 相关阅读:
    Centos下安装部署redis
    mysql 事务操作
    python 基础杂货铺
    6、Django 第三方工具
    5、Django
    4、django 模板
    RPC框架--missian框架
    jvm详情——7、jvm调优基本配置、方案
    jvm详情——6、堆大小设置简单说明
    jvm详情——5、选择合适的垃圾收集算法
  • 原文地址:https://www.cnblogs.com/h-lka/p/14231806.html
Copyright © 2011-2022 走看看