zoukankan      html  css  js  c++  java
  • HDU 4609 3-idiots FFT+容斥

    一点吐槽:我看网上很多分析,都是在分析这个题的时候,讲了半天的FFT,其实我感觉更多的把FFT当工具用就好了

    分析:这个题如果数据小,统计两个相加为 x 的个数这一步骤(这个步骤其实就是求卷积啊),完全可以母函数,无奈数据很大,就用FFT了

            然后难点在于最后的统计,要减去自身,两个都大的,一大一小,包含自身,这是用到了容斥,再做相似的题的时候,应该多看看这方面

    注:再次高度仰慕kuangbin神,这是我FFT的第二题,也是第二次用kuangbin FFT模板

    #include <stdio.h>
    #include <iostream>
    #include <algorithm>
    #include <string.h>
    #include <vector>
    #include <math.h>
    #include <map>
    using namespace std;
    typedef long long LL;
    const int INF=0x3f3f3f3f;
    const int N=4e5+5;
    const double pi = acos(-1.0);
    struct complex{
      double r,i;
      complex(double R=0,double I=0){
        r=R;i=I;
      }
      complex operator+(const complex &a)const{
        return complex(r+a.r,i+a.i);
      }
      complex operator-(const complex &a)const{
        return complex(r-a.r,i-a.i);
      }
      complex operator*(const complex &a)const{
        return complex(r*a.r-i*a.i,r*a.i+i*a.r);
      }
    };
    void change(complex x[],int len){
       int i,j,k;
       for(i=1,j=len/2;i<len-1;++i){
         if(i<j)swap(x[i],x[j]);
         k=len/2;
         while(j>=k){j-=k;k>>=1;}
         if(j<k)j+=k;
       }
    }
    void fft(complex x[],int len,int on){
       change(x,len);
       for(int i=2;i<=len;i<<=1){
        complex wn(cos(-on*2*pi/i),sin(-on*2*pi/i));
        for(int j=0;j<len;j+=i){
          complex w(1,0);
          for(int k=j;k<j+i/2;++k){
              complex u = x[k];
              complex t = w*x[k+i/2];
              x[k]=u+t;
              x[k+i/2]=u-t;
              w=w*wn;
          }
        }
       }
       if(on==-1)for(int i=0;i<len;++i)x[i].r/=len;
    }
    complex x[N];
    int a[N>>1];
    LL num[N],sum[N];
    int main(){  
      int T,n;
      scanf("%d",&T);
      while(T--){
        scanf("%d",&n);
        memset(num,0,sizeof(num));
        for(int i=0;i<n;++i){scanf("%d",&a[i]);++num[a[i]];}
        sort(a,a+n);
        int len1 = a[n-1] + 1,len = 1;
        while(len<2*len1)len<<=1;
        for(int i=0;i<len1;++i)x[i]=complex(num[i],0);
        for(int i=len1;i<len;++i)x[i]=complex(0,0);
        fft(x,len,1);
        for(int i=0;i<len;++i)x[i]=x[i]*x[i];
        fft(x,len,-1);
        for(int i=0;i<len;++i)
         num[i]=(long long)(x[i].r+0.5);
        len=2*a[n-1];
        for(int i=0;i<n;++i)--num[a[i]+a[i]];
        for(int i=1;i<=len;++i)num[i]>>=1;
        for(int i=1;i<=len;++i)sum[i]=sum[i-1]+num[i];
        LL cnt=0;
        for(int i=0;i<n;++i){
          cnt+=sum[len]-sum[a[i]];
          cnt-=1ll*(n-1-i)*i;
          cnt-=(n-1);
          cnt-=1ll*(n-1-i)*(n-i-2)/2;
        }
        LL tot=1ll*n*(n-1)*(n-2)/6;
        printf("%.7f
    ",1.0*cnt/tot);    
      }
      return 0;
    }
    View Code
  • 相关阅读:
    Python列表、元组、字典、集合的方法
    Python字符串方法总结
    进程、线程、协和的对比
    案例:图片下载器
    使用gevent实现多任务
    使用greenle完成多任务
    使用yield完成多任务
    生成器总结
    生成器send函数
    生成器yield关键字
  • 原文地址:https://www.cnblogs.com/shuguangzw/p/5689946.html
Copyright © 2011-2022 走看看