快速傅里叶变换FFT

是lzh学长讲过以后,又看了小迪的博客,才学会的fft

小迪这个博客太推荐了,一学就会https://www.cnblogs.com/RabbitHu/p/FFT.html

模板

#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;
}

 

OJ数据出问题了,我也不知道代码能不能过

具体思路见这个博客:https://blog.csdn.net/qq_33929112/article/details/54590319

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<complex>
#define PI (acos(-1.0))
#define maxn 400010
using namespace std;
double q[maxn];
complex<double>f[maxn],g[maxn],h[maxn];
int id[maxn],n;

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(){
    scanf("%d",&n);
    for(int i=0;i<n;i++){
        scanf("%lf",&q[i]);
        f[i]=q[i];
        h[n-i-1]=q[i];
    }
    for(int i=1;i<n;i++){
        g[i]=1.0/i/i;
    }
    int l=0,N=1,M=(n-1)*2;
    while(N<=M)N<<=1,l++;
    for(int i=0;i<N;i++)id[i]=(id[i>>1]>>1)|((i&1)<<(l-1));
    fft(f,N,1);fft(g,N,1);fft(h,N,1);
    for(int i=0;i<N;i++)f[i]=f[i]*g[i];
    for(int i=0;i<N;i++)h[i]=h[i]*g[i];
    fft(f,N,-1);fft(h,N,-1);
    for(int i=0;i<n;i++){
        double ans=f[i].real()-h[n-i-1].real();
        printf("%.10lf\n",ans);
    }
    return 0;
}

 

posted @ 2020-07-09 11:48  Echo宝贝儿  阅读(310)  评论(0编辑  收藏  举报