版权声明:随意转载哦......但还是请注明出处吧: https://blog.csdn.net/dreaming__ldx/article/details/85616404
传送门
经典题。
题意简述:给定
个长度分别为
的木棒,问随机选择3个木棒能够拼成三角形的概率。
思路:考虑对于木棒构造出生成函数然后可以
出两个木棒能够生成的边长和的生成函数 注意去重
我们还可以在读入的时候顺便统计出
表示长度
的木棒有多少根。
然后可以算出选出3个木棒不能拼成三角形的方案数,简单容斥一下再算出总选法数即可。
代码:
#include<bits/stdc++.h>
#define ri register int
using namespace std;
inline int read(){
int ans=0;
char ch=getchar();
while(!isdigit(ch))ch=getchar();
while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
return ans;
}
typedef long long ll;
struct Cp{
double x,y;
Cp(double x=0.0, double y=0.0):x(x),y(y){};
friend inline Cp operator+(const Cp&a,const Cp&b){return (Cp){a.x+b.x,a.y+b.y};}
friend inline Cp operator-(const Cp&a,const Cp&b){return (Cp){a.x-b.x,a.y-b.y};}
friend inline Cp operator*(const double&a,const Cp&b){return (Cp){a*b.x,a*b.y};}
friend inline Cp operator*(const Cp&a,const Cp&b){return (Cp){a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x};}
friend inline Cp operator/(const Cp&a,const double&b){return (Cp){a.x/b,a.y/b};}
};
int lim,tim;
vector<Cp>A,B;
vector<int>pos;
inline void init(const int&up){
lim=1,tim=0;
while(lim<=up)lim<<=1,++tim;
pos.resize(lim),A.resize(lim),B.resize(lim),pos[0]=0;
for(ri i=0;i<lim;++i)pos[i]=(pos[i>>1]>>1)|((i&1)<<(tim-1));
}
const double pi=acos(-1.0);
inline void fft(vector<Cp>&a,const int&type){
for(ri i=0;i<lim;++i)if(i<pos[i])swap(a[i],a[pos[i]]);
for(ri mid=1;mid<lim;mid<<=1){
Cp wn(cos(pi/mid),type*sin(pi/mid));
for(ri j=0,len=mid<<1;j<lim;j+=len){
Cp w(1,0),a0,a1;
for(ri k=0;k<mid;++k,w=w*wn){
a0=a[j+k],a1=a[j+k+mid]*w;
a[j+k]=a0+a1,a[j+k+mid]=a0-a1;
}
}
}
if(type==-1)for(ri i=0;i<lim;++i)a[i]=a[i]/lim;
}
struct poly{
vector<Cp>a;
poly(int k=0,int x=0){a.resize(k+1),a[k]=x;}
inline Cp&operator[](const int&k){return a[k];}
inline const Cp&operator[](const int&k)const{return a[k];}
inline int deg()const{return a.size()-1;}
inline poly extend(const int&k){poly ret=*this;return ret.a.resize(k+1),ret;}
friend inline poly operator*(const poly&a,const poly&b){
int n=a.deg(),m=b.deg();
init(n+m);
poly ret(lim);
for(ri i=0;i<=n;++i)A[i]=a[i];
for(ri i=0;i<=m;++i)B[i]=b[i];
for(ri i=n+1;i<lim;++i)A[i]=(0,0);
for(ri i=m+1;i<lim;++i)B[i]=(0,0);
fft(A,1),fft(B,1);
for(ri i=0;i<lim;++i)A[i]=A[i]*B[i];
return fft(A,-1),ret.a=A,ret;
}
};
const int N=1e5+5;
int n,x[N],mx;
poly a;
ll sum,cnt[N*2];
int main(){
for(ri tt=read();tt;--tt){
fill(cnt,cnt+mx+1,0);
n=read(),mx=0;
for(ri i=1;i<=n;++i)mx=max(mx,x[i]=read()),++cnt[x[i]];
for(ri i=1;i<=2*mx;++i)cnt[i]+=cnt[i-1];
a=a.extend(mx);
for(ri i=0;i<=mx;++i)a[i]=(0,0);
for(ri i=1;i<=n;++i)a[x[i]].x+=1;
a=a*a,mx<<=1;
for(ri i=1;i<=n;++i)a[x[i]<<1].x-=1;
sum=(ll)n*(n-1)*(n-2);
for(ri i=1;i<=mx;++i)sum-=(ll)(a[i].x+0.5)*(cnt[i-1]-2);
sum=(ll)n*(n-1)*(n-2)/6-sum/2;
printf("%.7LF\n",(long double)(sum*6.0)/((long double)n*(n-1)*(n-2)));
}
return 0;
}