Category : FFT
Problem:
Given n(10^5) sticks.Picking 3 sticks from there. What is the probability so that it forms a triangle.
Solution:
Notations:
a[] -> The length of the sticks are stored
cnt[] -> cnt[i] denotes how many time length i occur
Let a[]= {1,2,3,3}
From this array picking two different integer, what length can we make?
1+2=3,
1+3=4,
1+3=4
2+3=5,
2+3=5,
3+3=6,
So We can represent them taking the occurance of the numbers. as follows
Table 1
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8
0 | 0 | 0 | 1 | 2 | 2 | 1 | 0 | 0
Now How to use FFT ?
Okay make polynomial of cnt[] array.
Thus,
The representation of this :
Table 2
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8
0 | 0 | 1 | 2 | 5 | 4 | 4 | 0 | 0
You can guess how we find E^2, now can we find the prevous from this ?
{1,2,3,3} * {1,2,3,3}
By picking one from first and one from other,
1+1=2;
1+2=3;
1+3=4;
1+3=4;
2+1=3;
2+2=4;
2+3=5;
2+3=5;
3+1=4;
3+2=5;
3+3=6
3+3=6;
3+1=4;
3+2=5;
3+3=6
3+3=6;
So we represent this to array, it would look like the mentioned.
Now how to transform so that it generates table 1:
Note : For table 2,
a interger is adding to itself
1 + 2, 2+1, generates 2 but in table 1, it was generating 1, as permutation does not matter.
Using this above condition we can Transform 2 to Table 1
So, # minus num[a[i]*2] –, for every i
# divide each by 2 , num[i]/=2;
Now we have the Table 1 array.
How do we find the desired answer ?
sort the whole array,then take each length to be longest length of the triangle, So the summation of other sticks should be greater than this one.
details in code comment.
/*
*************************
Id : Matrix.code
Task: HDU - 4609
Date: 2016-02-07
**************************
*/
#include <bits/stdc++.h>
using namespace std;
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
template <typename T>
using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;
/*------- Constants---- */
#define Long long long
#define ull unsigned long long
#define mod 1000000007
#define MEMSET_INF 63
#define MEM_VAL 1061109567
#define forn(i,n) for( int i=0 ; i < n ; i++ )
#define mp(i,j) make_pair(i,j)
#define lop(i,a,b) for( int i = (a) ; i < (b) ; i++)
#define pb(a) push_back((a))
#define SZ(a) (int) a.size()
#define all(x) (x).begin(),(x).end()
#define gc getchar_unlocked
#define INF 1<<29
#define EPS 1e-9
#define Fr first
#define Sc second
#define Sz size()
#define lc ((n)<<1)
#define rc ((n)<<1|1)
#define db(x) cout << #x << " -> " << x << endl;
#define Di(n) int n;si(n)
#define Dii(a,b) int a,b;si(a);si(b)
#define Diii(a,b,c) int a,b,c;si(a);si(b);si(c)
#define Si(n) si(n)
#define Sii(a,b) si(a);si(b)
#define Siii(a,b,c) si(a);si(b);si(c)
#define min(a,b) ((a)>(b) ? (b) : (a) )
#define max(a,b) ((a)>(b) ? (a):(b))
/*---- short Cuts ------- */
#define ms(ara_name,value) memset(ara_name,value,sizeof(ara_name))
typedef pair<int, int> ii;
typedef vector<int > vi ;
typedef vector<Long> vl;
/*------ template functions ------ */
#ifndef getchar_unlocked
#define getchar_unlocked getchar
#endif
template<class T> inline void si(T &x){register int c = gc();x = 0;int neg = 0;for(;((c<48 | c>57) && c != '-');c = gc());
if(c=='-') {neg=1;c=gc();}for(;c>47 && c<58;c = gc()) {x = (x<<1) + (x<<3) + c - 48;}if(neg) x=-x;}
Long bigmod(Long p,Long e,Long M){Long ret = 1;for(; e > 0; e >>= 1){if(e & 1) ret = (ret * p) % M;p = (p * p) % M;} return ret;}
Long gcd(Long a,Long b){if(b==0)return a;return gcd(b,a%b);}
Long modinverse(Long a,Long M){return bigmod(a,M-2,M);}
void io(){freopen("/Users/MyMac/Desktop/in.txt","r",stdin);}
/*************************** END OF TEMPLATE ****************************/
const int N = 1<<18;
typedef long double T;
long double PI = acos(-1.0); // Without long double gives WA
struct Complex{
T x,y;
Complex(T x=0,T y=0):x(x),y(y){}
Complex operator + (const Complex &a) const{return Complex(x+a.x,y+a.y);};
Complex operator - (const Complex &a) const{return Complex(x-a.x,y-a.y);};
Complex operator * (const Complex &a) const{return Complex(x*a.x-y*a.y,x*a.y+y*a.x);};
};
struct Fast_Fourier{
Complex A[1 << 18];
int rev(int id, int len)
{ // Reversed bit value , 011 -> 110
int ret = 0;
for(int i = 0; (1 << i) < len; i++){
ret <<= 1;
if(id & (1 << i)) ret |= 1;
}
return ret;
}
void FFT(Complex a[], int len, int DFT)
{
for(int i = 0; i < len; i++) A[rev(i, len)] = a[i];
for(int s = 1; (1 << s) <= len; s++)
{
int m = (1 << s);
Complex wm = Complex(cos(DFT*2*PI/m), sin(DFT*2*PI/m));
for(int k = 0; k < len; k += m)
{
Complex w = Complex(1, 0);
for(int j = 0; j < (m >> 1); j++)
{
Complex t = w*A[k + j + (m >> 1)];
Complex u = A[k + j];
A[k + j] = u + t;
A[k + j + (m >> 1)] = u - t;
w = w*wm;
}
}
}
if(DFT == -1) for(int i = 0; i < len; i++) A[i].x /= len, A[i].y /= len;
for(int i = 0; i < len; i++) a[i] = A[i];
return;
}
}fft ;
Complex x[1<<18];
Long num[1<<18];
int a[N];
int cnt[N];
Long sum[N];
int main()
{
// freopen("in.txt","r",stdin);
Di(t);
while(t--) {
Long n;
Si(n);
int iM = 0;
for(int i= 0;i < n;i ++) {
Si(a[i]);
cnt[a[i]] ++;
iM = max(iM , a[i]);
}
sort(a,a+n);
int len = 1;
while(len <= 2 * iM) len *= 2;
for(int i= 0;i < len;i ++) {
x[i] = Complex(cnt[i],0);
}
fft.FFT(x,len,1);
for(int i= 0;i < len;i ++) {
x[i] = x[i] * x[i];
}
fft.FFT(x,len,-1);
for(int i= 0;i < len;i ++) {
num[i] = (Long)(x[i].x + .5 );
}
for(int i= 0; i < n; i ++) {
num[a[i] + a[i]] --;
}
for(int i= 0;i < len;i ++) {
num[i]/=2;
}
// prefix sum
for(int i= 1;i < len; i ++) {
sum[i] = num[i] + sum[i-1];
}
Long ans = 0;
for(int i= 0 ;i < n; i++ ) {
ans += sum[len-1] - sum[a[i]]; // # of ways such that summation of length > a[i]
ans -= (n-1-i) * i; // as a[i], is the largest,so there are (n-1-i) are bigger than a[i]. They with any number less tham a[i] is included in first case. So substract them.
ans -= (n-1);
ans -= (n-i-1) * (n-i-2) / 2; // number of ways where the both length > a[i] , subtract them.
}
Long tot = ((Long)n ) * (n-1) * (n-2)/6;
printf("%.7lf\n", ans*1./ tot);
ms(cnt,0);
}
return 0;
}