只想说弱爆了,学完FFT还是不知道思路,只好到网上看解题思路,标程和网上统计方法不同,不过都是求补集。
ACcode:
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
typedef long long LL;
const int NS=1<<18;
const double pi=acos(-1.0);
int n,N,a[NS];
LL num[NS];
struct Complex{
double re,im;
Complex():re(0.),im(0.){}
Complex(double x,double y):re(x),im(y){}
Complex operator + (const Complex tmp) const {
return Complex(re+tmp.re,im+tmp.im);
}
Complex operator - (const Complex tmp) const {
return Complex(re-tmp.re,im-tmp.im);
}
Complex operator * (const Complex tmp) const {
return Complex(re*tmp.re-im*tmp.im,re*tmp.im+im*tmp.re);
}
double real(){ return re; }
}P[NS],_P[NS];
int reve(int x,int len)
{
int y=0;
for (int i=0;i<len;x>>=1,i++)
y|=(x&1)?1<<(len-1-i):0;
return y;
}
void build(int n,int m,int pos,int &cnt)
{
if (m==n) {
_P[cnt++]=P[pos];
} else {
build(n,m<<1,pos,cnt);
build(n,m<<1,pos+m,cnt);
}
}
inline void FFT(int len,int oper)
{
// int t=0;
// for (;(1<<t)<len;t++);
// for (int i=0;i<len;i++)
// _P[reve(i,t)]=P[i];
// copy(_P,_P+len,P);
int cnt=0;
build(len,1,0,cnt);
copy(_P,_P+len,P);
for (int d=1;d<len;d<<=1)
{
int D=d<<1;
double u0=pi/d*oper;
Complex w,w0=Complex(cos(u0),sin(u0));
for (int i=0;i<len;i+=D)
{
w=Complex(1.0,0.0);
for (int j=0;j<d;j++)
{
Complex tmp=w*P[i+j+d];
P[i+j+d]=P[i+j]-tmp;
P[i+j]=P[i+j]+tmp;
w=w*w0;
}
}
}
}
inline void Mul()
{
for (int i=0;i<N;i++)
P[i]=Complex(num[i]+0.,0.);
FFT(N,1);
for (int i=0;i<N;i++)
P[i]=P[i]*P[i];
FFT(N,-1);
for (int i=0;i<N;i++)
num[i]=LL(P[i].real()/N+0.1);
for (int i=0;i<n;i++)
num[a[i]+a[i]]--;
for (int i=0;i<N;i++)
num[i]>>=1;
LL ans,tot;
ans=tot=(LL)n*(n-1)*(n-2)/6;
ans=0;
for (int i=1;i<N;i++)
num[i]+=num[i-1];
for (int i=0;i<n;i++)
{
ans+=num[N-1]-num[a[i]];
ans-=(LL)(n-i-1)*(n-i-2)/2;
ans-=(LL)(n-i-1)*i+n-1;
}
// for (int j=0,i=0;i<N;i++)
// if (num[i])
// {
// for (;j<n&&a[j]<i;j++);
// if (j==n) break;
// ans-=num[i]*(n-j);
// }
printf("%.7f\n",(double)ans/tot);
}
int main()
{
int T,x,y;
for (scanf("%d",&T);T;T--)
{
memset(num,0,sizeof(num));
scanf("%d",&n),x=0;
for (int i=0;i<n;i++)
{
scanf("%d",&a[i]);
num[a[i]]++;
x=max(x,a[i]+1);
}
for (N=NS;N>=(x<<2);N>>=1);
sort(a,a+n),Mul();
}
return 0;
}