题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4609
(fft) 经典套路,求 (n) 个数任意两个相加所得的数的种类/数量,只需要将数值当作指数,系数0/1表示有/没有或 (a_i) 表示该数值有 (a_i) 个,(fft) 即可,注意去重
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<stack>
#include<queue>
using namespace std;
typedef long long ll;
const int maxn = 3e5+7;
int T, n, m, N = 100000;
int l,r[maxn], t[maxn], c[maxn];
ll ans[maxn], sum[maxn];
int lim=1;
const double Pi = acos(-1.0);
struct complex{
double x,y;
complex(double xx=0,double yy=0) { x=xx,y=yy; }
}a[maxn],b[maxn];
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); }
void fft(complex *A,int type){
for(int i=0;i<lim;i++)
if(i<r[i]) swap(A[i],A[r[i]]);
for(int mid=1;mid<lim;mid<<=1){
complex Wn( cos(Pi/mid),type*sin(Pi/mid));
for(int r=mid<<1,j=0;j<lim;j+=r){
complex w(1,0);
for(int k=0;k<mid;k++,w=w*Wn){
complex x=A[j+k],y=w*A[j+mid+k];
A[j+k]=x+y;
A[j+mid+k]=x-y;
}
}
}
}
ll read(){ ll s=0,f=1; char ch=getchar(); while(ch<'0' || ch>'9'){ if(ch=='-') f=-1; ch=getchar(); } while(ch>='0' && ch<='9'){ s=s*10+ch-'0'; ch=getchar(); } return s*f; }
int main(){
T = read();
while(T--){
memset(a, 0, sizeof(a));
memset(b, 0, sizeof(b));
memset(t, 0, sizeof(t));
memset(c, 0, sizeof(c));
memset(ans, 0, sizeof(ans));
lim = 1, l = 0;
n=read();
for(int i = 1 ; i <= n ; ++i) t[i] = read(), ++c[t[i]];
for(int i=0;i<=N;i++) a[i].x = c[i];
while(lim <= N + N) lim<<=1,l++;
for(int i=0;i<lim;i++)
r[i]=(r[i>>1]>>1)|(i&1)<<(l-1);
fft(a,1);
for(int i=0;i<=lim;i++) a[i]=a[i]*a[i];
fft(a,-1);
for(int i=0;i<=N + N;i++){
ans[i] = (ll)(a[i].x/lim+0.5);
}
for(int i = 1 ; i <= n ; ++i) --ans[t[i] + t[i]];
for(int i = 0 ; i <= N + N ; ++i) {
ans[i] /= 2ll;
}
for(int i = 1 ; i <= N + N ; ++i){
sum[i] = sum[i - 1] + ans[i];
}
ll val = 0;
for(int i = 1 ; i <= n ; ++i){
val += sum[N + N] - sum[t[i]];
val -= 1ll * (i - 1) * (n - i);
val -= (n - 1);
val -= 1ll * (n - i) * (n - i - 1) / 2;
}
ll all = 1ll * n * (n - 1) * (n - 2) / 6ll;
printf("%.7lf
", (double) val / all);
}
return 0;
}