码迷,mamicode.com
首页 > 其他好文 > 详细

HDU 4609 3-idiots FFT+容斥

时间:2016-07-21 00:23:42      阅读:186      评论:0      收藏:0      [点我收藏+]

标签:

一点吐槽:我看网上很多分析,都是在分析这个题的时候,讲了半天的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\n",1.0*cnt/tot);    
  }
  return 0;
}
View Code

 

HDU 4609 3-idiots FFT+容斥

标签:

原文地址:http://www.cnblogs.com/shuguangzw/p/5689946.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!