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哦~
  • 相关阅读:
    HDU 2853 (KM最大匹配)
    HDU 2852 (树状数组+无序第K小)
    HDU 2851 (最短路)
    HDU 2846 (AC自动机+多文本匹配)
    MyBatis使用示例
    Hessian示例:Java和C#通信
    SQL Server2005配置同步复制
    【问】如何应对关系型数据库中列的不断增加
    Prolog学习:数独和八皇后问题
    Prolog学习:基本概念
  • 原文地址:https://www.cnblogs.com/SiriusRen/p/6532866.html
Copyright © 2011-2022 走看看