码迷,mamicode.com
首页 > 其他好文 > 详细

快速傅里叶变换FFT

时间:2020-07-09 12:31:09      阅读:80      评论:0      收藏:0      [点我收藏+]

标签:mes   scan   put   ble   math   pac   ++   color   char   

模板

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<complex>
#define maxn 4000010
#define PI (acos(-1.0))
using namespace std;
complex<double>a[maxn],b[maxn];
int id[maxn];
void fft(complex<double> *p,int N,int f){
    for(int i=0;i<=N;i++)
        if(id[i]>i)swap(p[i],p[id[i]]);
    for(int k=1;k<N;k<<=1){
        complex<double>wn(cos(PI/k),f*sin(PI/k));
        for(int j=0;j<N;j+=k<<1){
            complex<double>w(1,0);
            for(int i=0;i<k;i++,w=w*wn){
                complex<double>x=p[i+j];
                complex<double>y=p[i+j+k]*w;
                p[i+j]=x+y;
                p[i+j+k]=x-y;
            }
        }
    }
    if(f==-1)
        for(int i=0;i<N;i++)p[i]=p[i]/(double)N;
}
int main(){
    int N,M;
    scanf("%d%d",&N,&M);
    double x;
    for(int i=0;i<=N;i++){
        scanf("%lf",&x);
        a[i].real(x);
    }
    for(int i=0;i<=M;i++){
        scanf("%lf",&x);
        b[i].real(x);
    }
    M=N+M;N=1;
    int l=0;
    while(N<=M)N<<=1,l++;
    for(int i=0;i<=N;i++)id[i]=(id[i>>1]>>1)|((i&1)<<(l-1));
    fft(a,N,1);fft(b,N,1);
    for(int i=0;i<=N;i++)a[i]=a[i]*b[i];
    fft(a,N,-1);
    for(int i=0;i<=M;i++)
        printf("%d ",(int)(a[i].real()+0.5));
    return 0;
}

 

A - A * B Problem Plus

题意:求两个长度为50000位的大整数的乘积

解:fft之后进位,并特判为0的情况

注意fft计算时一定要用double类型,结果四舍五入取整数

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<complex>
#define maxn 400010
#define PI (acos(-1.0))
using namespace std;
complex<double>a[maxn],b[maxn];
char s1[maxn],s2[maxn];
int id[maxn],ans[maxn];
void fft(complex<double> *p,int N,int f){
    for(int i=0;i<=N;i++)
        if(id[i]>i)swap(p[i],p[id[i]]);
    for(int k=1;k<N;k<<=1){
        complex<double>wn(cos(PI/k),f*sin(PI/k));//点值化为系数表示,用共轭复数 
        for(int j=0;j<N;j+=k<<1){
            complex<double>w(1,0);
            for(int i=0;i<k;i++,w=w*wn){
                complex<double>x=p[i+j];
                complex<double>y=p[i+j+k]*w;
                p[i+j]=x+y;
                p[i+j+k]=x-y;
            }
        }
    }
    if(f==-1)
        for(int i=0;i<N;i++)p[i]=p[i]/(double)N;
}

int main(){
    int N,M;
//    scanf("%d%d",&N,&M);
    int x;
    while(scanf("%s",s1)!=EOF){
        memset(a,0,sizeof(a));
        memset(b,0,sizeof(b));
        scanf("%s",s2);
        N=strlen(s1);
        M=strlen(s2); 
        for(int i=0;i<N;i++){
            x=s1[i]-0;
            a[i].real(x);
        }
        for(int i=0;i<M;i++){
            x=s2[i]-0;
            b[i].real(x);
        }
        M=N+M;N=1;
        int l=0;
        while(N<=M)N<<=1,l++;
        for(int i=0;i<=N;i++)id[i]=(id[i>>1]>>1)|((i&1)<<(l-1));
        fft(a,N,1);fft(b,N,1);
        for(int i=0;i<=N;i++)a[i]=a[i]*b[i];
        fft(a,N,-1);
        for(int i=0;i<M-1;i++)ans[i]=(int)(a[i].real()+0.5);
        for(int i=M-2;i>0;i--){
            if(ans[i]>=10){
                ans[i-1]+=ans[i]/10;
                ans[i]%=10;
            }
        }
        bool flag=0;
        for(int i=0;i<M-1;i++){
            if(ans[i]!=0)flag=1;
            if(flag)printf("%d",ans[i]);
        }
        if(!flag)printf("0");
        puts("");
    } 
    
    return 0;
}

 

快速傅里叶变换FFT

标签:mes   scan   put   ble   math   pac   ++   color   char   

原文地址:https://www.cnblogs.com/thmyl/p/13272816.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!