zoukankan      html  css  js  c++  java
  • 快速傅里叶变换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
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    使用日历控件的一些体会(downmoon)
    带附加条件的NewID()用法
    微软的招聘哲学——做微软人的五大核心素质(摘自《微软360度》)
    彻底禁用fckEditor的上传功能(含防止Type漏洞问题)
    Remote Access Connection Manager 服务因下列错误而停止解决办法
    GridView如何更新批量数据和单条记录?
    .net1.1与.net2.0在加载ascx文件的控件时有所不同(Downmoon)
    牛羊吃草问题求解(downmoon)
    c#操作ecxel的一些资源(downmoon搜集)
    安装sql2008 enterprise (English正式版)图解
  • 原文地址:https://www.cnblogs.com/thmyl/p/13272816.html
Copyright © 2011-2022 走看看