zoukankan      html  css  js  c++  java
  • UOJ #34 多项式乘法

    题目链接:多项式乘法

      保存一发FFT与NTT板子。

      学习链接:从多项式乘法到快速傅里叶变换 FFT NTT

      注意差值回来的时候不取反也是可以的,只不过需要把数组(reverse)一下(根据单位复数根的性质应该不难理解)

      代码(FFT):

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<complex>
    #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
    #define C complex<double>
    #define maxn 300010
    #define pi (acos(-1))
    
    using namespace std;
    typedef long long llg;
    
    int n,m,L,R[maxn];
    C a[maxn],b[maxn];
    
    int getint(){
    	int w=0;bool q=0;
    	char c=getchar();
    	while((c>'9'||c<'0')&&c!='-') c=getchar();
    	if(c=='-') c=getchar(),q=1;
    	while(c>='0'&&c<='9') w=w*10+c-'0',c=getchar();
    	return q?-w:w;
    }
    
    void fft(C *a){
    	for(int i=0;i<n;i++) if(i<R[i]) swap(a[i],a[R[i]]);
    	for(int i=1;i<n;i<<=1){
    		C wn(cos(pi/i),sin(pi/i)),x,y;
    		for(int j=0;j<n;j+=(i<<1)){
    			C w(1,0);
    			for(int k=0;k<i;k++,w*=wn){
    				x=a[j+k]; y=w*a[j+i+k];
    				a[j+k]=x+y; a[j+i+k]=x-y;
    			}
    		}
    	}
    }
    
    int main(){
    	File("a");
    	n=getint(); m=getint();
    	for(int i=0;i<=n;i++) a[i]=getint();
    	for(int i=0;i<=m;i++) b[i]=getint();
    	m+=n; for(n=1;n<=m;n<<=1) L++;
    	for(int i=0;i<n;i++) R[i]=(R[i>>1]>>1)|((i&1)<<(L-1));
    	fft(a); fft(b);
    	for(int i=0;i<n;i++) a[i]*=b[i];
    	fft(a); reverse(a+1,a+n);
    	for(int i=0;i<=m;i++) printf("%d ",(int)round(a[i].real()/n));
    	return 0;
    }
    

      代码(NTT):

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<complex>
    #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
    #define maxn 300010
    #define mod 998244353
    
    using namespace std;
    typedef long long llg;
    
    const int g=3;
    int n,m,L,R[maxn],N;
    int a[maxn],b[maxn];
    
    int getint(){
    	int w=0;bool q=0;
    	char c=getchar();
    	while((c>'9'||c<'0')&&c!='-') c=getchar();
    	if(c=='-') c=getchar(),q=1;
    	while(c>='0'&&c<='9') w=w*10+c-'0',c=getchar();
    	return q?-w:w;
    }
    
    int qpow(int x,int y){
    	int s=1;
    	while(y){
    		if(y&1) s=1ll*s*x%mod;
    		x=1ll*x*x%mod; y>>=1;
    	}
    	return s;
    }
    
    void ntt(int *a){
    	for(int i=0;i<n;i++) if(i<R[i]) swap(a[i],a[R[i]]);
    	for(int i=1;i<n;i<<=1){
    		int gn=qpow(g,(mod-1)/(i<<1)),x,y;
    		for(int j=0;j<n;j+=(i<<1)){
    			int g=1;
    			for(int k=0;k<i;k++,g=1ll*g*gn%mod){
    				x=a[j+k]; y=1ll*g*a[j+i+k]%mod;
    				a[j+k]=x+y; if(a[j+k]>=mod) a[j+k]-=mod;
    				a[j+i+k]=x-y; if(x<y) a[j+i+k]+=mod;
    			}
    		}
    	}
    }
    
    int main(){
    	File("a");
    	n=getint(); m=getint();
    	for(int i=0;i<=n;i++) a[i]=getint();
    	for(int i=0;i<=m;i++) b[i]=getint();
    	m+=n; for(n=1;n<=m;n<<=1) L++;
    	for(int i=0;i<n;i++) R[i]=(R[i>>1]>>1)|((i&1)<<(L-1));
    	ntt(a); ntt(b); N=qpow(n,mod-2);
    	for(int i=0;i<n;i++) a[i]=1ll*a[i]*b[i]%mod;
    	ntt(a); reverse(a+1,a+n);
    	for(int i=0;i<=m;i++) printf("%d ",1ll*a[i]*N%mod);
    	return 0;
    }
    
  • 相关阅读:
    iframe显示高度自适应 兼容多浏览器
    Asp.Net在Global.asax中实现URL 的重写
    文件流下载 ASP.NET
    Asp.Net实现全局定时器功能
    C#中获取本机IP地址,子网掩码,网关地址
    Asp.Net缓存实例
    Google API 天气数据缓存到一个XML中
    获取服务器信息
    C# NET 中英混合字符串截断实例
    Asp.Net实现长文章分页显示功能
  • 原文地址:https://www.cnblogs.com/lcf-2000/p/6371686.html
Copyright © 2011-2022 走看看