zoukankan      html  css  js  c++  java
  • BZOJ 3509 分块FFT

    思路:

    跟今年WC的题几乎一样 (但是这道题有重 不能用bitset水过去)

    正解:分块FFT

    http://blog.csdn.net/geotcbrl/article/details/50636401    from GEOTCBRL 

    可以看看hgr的题解..写得很详细

    //By SiriusRen
    #include <cmath>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    const double pi=acos(-1);
    const int N=100050;
    int n,nn,num[N],R[N],L,Block,block[N],cnt[50][N];
    long long ans;
    struct Complex{
        double x,y;Complex(){}
        Complex(double X,double Y){x=X,y=Y;}
    }A[N],B[N],C[N];
    Complex operator+(Complex a,Complex b){return Complex(a.x+b.x,a.y+b.y);}
    Complex operator-(Complex a,Complex b){return Complex(a.x-b.x,a.y-b.y);}
    Complex operator*(Complex a,Complex b){return Complex(a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x);}
    Complex operator/(Complex a,int b){return Complex(a.x/b,a.y/b);}
    void FFT(Complex *a,int f){
        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){
            Complex wn=Complex(cos(pi/i),f*sin(pi/i));
            for(int j=0;j<n;j+=(i<<1)){
                Complex w=Complex(1,0);
                for(int k=0;k<i;k++,w=w*wn){
                    Complex x=a[j+k],y=w*a[j+k+i];
                    a[j+k]=x+y,a[j+k+i]=x-y;
                }
            }
        }
        if(!~f)for(int i=0;i<n;i++)a[i]=a[i]/n;
    }
    int main(){
        scanf("%d",&nn);
        for(int i=1;i<=nn;i++)scanf("%d",&num[i]);
        for(n=1;n<=60000;n<<=1)L++;
        for(int i=0;i<n;i++)R[i]=(R[i>>1]>>1)|((i&1)<<(L-1));
        Block=min(int(sqrt(nn)*10),nn);
        for(int i=1;i<=nn;i++)block[i]=(i-1)/Block+1;
        for(int i=1;i<=nn;i++)cnt[block[i]][num[i]]++;
        for(int I=1;I<=block[nn];I++){
            int L=lower_bound(block+1,block+1+nn,I)-block,R=upper_bound(block+1,block+1+nn,I)-block-1;
            for(int j=L;j<=R;j++){
                cnt[I][num[j]]--;
                for(int i=L;i<j;i++)
                    if(num[j]*2-num[i]>=0)ans+=cnt[I][num[j]*2-num[i]];
            }
        }
        for(int i=1;i<=nn;i++)cnt[0][num[i]]++;
        for(int I=1;I<=block[nn];I++){
            int L=lower_bound(block+1,block+1+nn,I)-block,R=upper_bound(block+1,block+1+nn,I)-block-1;
            for(int i=L;i<=R;i++)cnt[0][num[i]]--;
            for(int j=L;j<=R;j++)
                for(int i=L;i<j;i++)
                    if(num[j]*2-num[i]>=0)ans+=cnt[0][num[j]*2-num[i]];
        }
        for(int i=1;i<=nn;i++)cnt[0][num[i]]++;
        for(int I=block[nn];I;I--){
            int L=lower_bound(block+1,block+1+nn,I)-block,R=upper_bound(block+1,block+1+nn,I)-block-1;
            for(int i=L;i<=R;i++)cnt[0][num[i]]--;
            for(int k=L;k<=R;k++)
                for(int j=k-1;j>=L;j--)
                    if(num[j]*2-num[k]>=0)ans+=cnt[0][num[j]*2-num[k]];
        }
        for(int I=1;I<=block[nn];I++){
            for(int i=0;i<n;i++)A[i].x=A[i].y=B[i].x=B[i].y=0;
            int L=lower_bound(block+1,block+1+nn,I)-block,R=upper_bound(block+1,block+1+nn,I)-block-1;
            for(int i=1;i<L;i++)A[num[i]].x++;
            for(int i=R+1;i<=nn;i++)B[num[i]].x++;
            FFT(A,1),FFT(B,1);
            for(int i=0;i<n;i++)C[i]=A[i]*B[i];
            FFT(C,-1);
            for(int i=L;i<=R;i++)ans+=(long long)(C[num[i]*2].x+0.2);
        }
        printf("%lld
    ",ans);
    }
    分块FFT哦~
  • 相关阅读:
    Python 解LeetCode:Intersection of Two Arrays
    flask中使用xlsxwriter导出excel文件
    python的xlwt模块的常用方法
    线程池理解
    内存屏障理解
    中断上半部,下半部理解
    DPDK l2fwd源码学习
    如何用perf工具
    如何迅速分析出系统CPU的瓶颈在哪里?
    怎么理解Linux软中断?
  • 原文地址:https://www.cnblogs.com/SiriusRen/p/6532866.html
Copyright © 2011-2022 走看看