题目大意
给定n条边的边值,求任意取三条边能组成三角形的概率
这里概率 P = valid/tot
tot = (n-2)*(n-1)*n/6是没问题的
valid表示合法的方式
先考虑,任意两条边组合形成方法的总数
因为边值在100000的范围内,这里组合用fft计算
得到最后形成和为 i 的两条边的方法数为 num[i]
这里计算后要记得减去取两条相同边的情况,还有 取 3,4 和 4,3是一样的,要记得除以2
最后跑个n的循环,每次将当前边作为排序后(主要是因为有长度相同的边才这么考虑)次序最大的边,然后保证得到的和是两条在它前面的边组成的
这个计算就需要求个总方法数的前缀和了
取到所有和大于当前边的方法数,减去由两条比它大的边组成的情况(n-i)*(n-i-1)/2,一个比他大一个比他小组成的(n-i)*(i-1),还有它其余任意一条边组成的(n-1)
1 #include <cstdio> 2 #include <cstring> 3 #include <cmath> 4 #include <iostream> 5 #include <algorithm> 6 using namespace std; 7 #define N 100005 8 #define ll long long 9 const double PI = acos(-1.0); 10 11 int n , a[N] , cnt[N] ; 12 ll num[N<<2] , sum[N<<2]; 13 14 struct complex{ 15 double r , i; 16 complex(double r=0 , double i=0):r(r),i(i){} 17 complex operator+(const complex &a) const{ 18 return complex(r+a.r , i+a.i); 19 } 20 complex operator-(const complex &a) const{ 21 return complex(r-a.r , i-a.i); 22 } 23 complex operator*(const complex &a) const{ 24 return complex(r*a.r-i*a.i , r*a.i+i*a.r); 25 } 26 }; 27 28 void change(complex y[] , int len) 29 { 30 int i,j,k; 31 for(i=1 , j=len/2 ; i<len-1 ; i++){ 32 if(i<j) swap(y[i],y[j]); 33 k = len/2; 34 while(j>=k){ 35 j-=k; 36 k/=2; 37 } 38 if(j<k) j+=k; 39 } 40 } 41 42 void fft(complex y[] , int len , int on) 43 { 44 change(y , len); 45 for(int i=2 ; i<=len ; i<<=1){ 46 complex wn(cos(-on*2*PI/i) , sin(-on*2*PI/i)); 47 for(int j=0 ; j<len ; j+=i){ 48 complex w(1,0); 49 for(int k=j ; k<j+i/2 ; k++){ 50 complex u = y[k]; 51 complex t = w*y[k+i/2]; 52 y[k] = u+t; 53 y[k+i/2] = u-t; 54 w = w*wn; 55 } 56 } 57 } 58 if(on==-1) 59 for(int i=0 ; i<len ; i++) 60 y[i].r /= len; 61 62 } 63 complex x[N<<2]; 64 65 int main() 66 { 67 // freopen("a.in" , "r" , stdin); 68 int T; 69 scanf("%d" , &T); 70 while(T--){ 71 scanf("%d" , &n); 72 int mx = 0; 73 memset(cnt , 0 , sizeof(cnt)); 74 for(int i=1 ; i<=n ; i++){ 75 scanf("%d" , &a[i]); 76 cnt[a[i]]++ , mx=max(mx , a[i]); 77 } 78 int len = 1; 79 while(len<2*(mx+1)) len<<=1; 80 for(int i=0 ; i<=mx ; i++) x[i] = complex(cnt[i] , 0); 81 for(int i=mx+1 ; i<len ; i++) x[i] = complex(0 , 0); 82 fft(x , len , 1); 83 for(int i=0 ; i<len ; i++) 84 x[i] = x[i]*x[i]; 85 fft(x , len , -1); 86 for(int i=0 ; i<len ; i++) num[i] = (ll)(x[i].r+0.5); 87 for(int i=1 ; i<=n ; i++) num[a[i]+a[i]]--; 88 for(int i=0 ; i<len ; i++){ 89 num[i]/=2; 90 if(i) sum[i] = sum[i-1]+num[i]; 91 } 92 ll ans = 0; 93 sort(a+1 , a+n+1); 94 for(int i=1 ; i<=n ; i++){ 95 ll val = sum[len-1]-sum[a[i]]; 96 val = val - (n-1); 97 val = val - (ll)(n-i)*(i-1); 98 val = val - (ll)(n-i)*(n-i-1)/2; 99 // cout<<i<<" "<<a[i]<<" "<<sum[len-1]-sum[a[i]]<<" "<<val<<endl; 100 ans = ans+val; 101 } 102 printf("%.7f\n" , ans*6.0/((ll)n*(n-1)*(n-2))); 103 } 104 return 0; 105 }