hdu 4609 3-idiots(快速傅里叶FFT)

比较裸的FFT(快速傅里叶变换),也是为了这道题而去学的,厚的白书上有简单提到,不过还是推荐看算法导论,讲的很详细。

代码的话是照着别人敲的,推荐:http://www.cnblogs.com/kuangbin/archive/2013/07/24/3210565.html写的很详细。

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 #include<cmath>
  5 using namespace std;
  6 #define LL __int64
  7 
  8 const double PI=acos(-1.0);
  9 
 10 struct complex{     //实数:r实部,i虚部
 11     double r,i;
 12     complex(double rr=0,double ii=0)
 13     {
 14         r=rr;
 15         i=ii;
 16     }
 17     complex operator +(const complex &b)
 18     {
 19         return complex(r+b.r,i+b.i);
 20     }
 21     complex operator -(const complex &b)
 22     {
 23         return complex(r-b.r,i-b.i);
 24     }
 25     complex operator *(const complex &b)
 26     {
 27         return complex(r*b.r-i*b.i,r*b.i+i*b.r);
 28     }
 29 };
 30 
 31 void change(complex y[],int len)  //位逆序置换
 32 {
 33     int i,j,k;
 34     for(i=1,j=len/2;i<len-1;i++)
 35     {
 36         if(i<j)
 37             swap(y[i],y[j]);
 38         k=len/2;
 39         while(j>=k)
 40         {
 41             j-=k;
 42             k/=2;
 43         }
 44         if(j<k)
 45             j+=k;
 46     }
 47 }
 48 
 49 void fft(complex y[],int len,int on)
 50 {
 51     change(y,len);
 52     for(int h=2;h<=len;h<<=1)
 53     {
 54         complex wn(cos(-on*2*PI/h),sin(-on*2*PI/h));
 55         for(int j=0;j<len;j+=h)
 56         {
 57             complex w(1,0);
 58             for(int k=j;k<j+h/2;k++)
 59             {
 60                 complex u=y[k];
 61                 complex t=w*y[k+h/2];
 62                 y[k]=u+t;
 63                 y[k+h/2]=u-t;
 64                 w=w*wn;
 65             }
 66         }
 67     }
 68     if(on==-1)
 69         for(int i=0;i<len;i++)
 70             y[i].r/=len;
 71 }
 72 
 73 const int MAXN=400040;
 74 complex x1[MAXN];
 75 int a[MAXN/4];
 76 LL num[MAXN];
 77 LL sum[MAXN];
 78 
 79 int main()
 80 {
 81     int T,n;
 82     scanf("%d",&T);
 83     while(T--)
 84     {
 85         scanf("%d",&n);
 86         memset(num,0,sizeof(num));
 87         for(int i=0;i<n;i++)
 88         {
 89             scanf("%d",&a[i]);
 90             num[a[i]]++;
 91         }
 92 //FFT
 93         sort(a,a+n);
 94         int len1=a[n-1]+1;
 95         int len=1;
 96         while(len<2*len1)
 97             len<<=1;
 98         for(int i=0;i<len1;i++)
 99             x1[i]=complex(num[i],0);
100         for(int i=len1;i<len;i++)  //补0
101             x1[i]=complex(0,0);
102         fft(x1,len,1);              //求值
103         for(int i=0;i<len;i++)     //乘法
104             x1[i]=x1[i]*x1[i];
105         fft(x1,len,-1);             //插值
106 //
107         for(int i=0;i<len;i++)
108             num[i]=(LL)(x1[i].r+0.5);
109         len=2*a[n-1];
110         for(int i=0;i<n;i++)
111             num[a[i]+a[i]]--;
112         for(int i=1;i<=len;i++)
113             num[i]/=2;
114         sum[0]=0;
115         for(int i=1;i<=len;i++)
116             sum[i]=sum[i-1]+num[i];
117         LL cnt=0;
118         for(int i=0;i<n;i++)
119         {
120             cnt+=sum[len]-sum[a[i]];
121             cnt-=(LL)(n-1-i)*(n-i-2)/2;
122             cnt-=(n-1);
123             cnt-=(LL)(n-1-i)*(n-i-2)/2;
124         }
125         LL tot=(LL)n*(n-1)*(n-2)/6;
126         printf("%.7f\n",(double)cnt/tot);
127     }
128     return 0;
129 }
View Code

 

posted @ 2013-07-28 09:25  Thousand Sunny  阅读(272)  评论(0编辑  收藏  举报