比较裸的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 ",(double)cnt/tot); 127 } 128 return 0; 129 }