天天看点

HDU 4609 3-idiots

Description

King OMeGa catched three men who had been streaking in the street. Looking as idiots though, the three men insisted that it was a kind of performance art, and begged the king to free them. Out of hatred to the real idiots, the king wanted to check if they were lying. The three men were sent to the king's forest, and each of them was asked to pick a branch one after another. If the three branches they bring back can form a triangle, their math ability would save them. Otherwise, they would be sent into jail. 

However, the three men were exactly idiots, and what they would do is only to pick the branches randomly. Certainly, they couldn't pick the same branch - but the one with the same length as another is available. Given the lengths of all branches in the forest, determine the probability that they would be saved. 

Input

An integer T(T≤100) will exist in the first line of input, indicating the number of test cases. 

Each test case begins with the number of branches N(3≤N≤10 

5). 

The following line contains N integers a_i (1≤a_i≤10 

5), which denotes the length of each branch, respectively. 

Output

Output the probability that their branches can form a triangle, in accuracy of 7 decimal places.

Sample Input

2

4

1 3 3 4

4

2 3 3 4

Sample Output

0.5000000

1.0000000

#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
typedef long long LL;
const int maxn = 100005;
const double pi = acos(-1.0);
const int low(int x){ return x&-x; }//树状数组的lowbit,可以计算二进制最右边的1
int T;

class FFT
{
private:
  const static int maxn = 270000;//要注意长度是2^k方
  class Plural
  {
  public:
    double x, y;
    Plural(double x = 0.0, double y = 0.0) :x(x), y(y){}
    Plural operator +(const Plural &a)
    {
      return Plural(x + a.x, y + a.y);
    }
    Plural operator -(const Plural &a)
    {
      return Plural(x - a.x, y - a.y);
    }
    Plural operator *(const Plural &a)
    {
      return Plural(x*a.x - y*a.y, x*a.y + y*a.x);
    }
    Plural operator /(const double &u)
    {
      return Plural(x / u, y / u);
    }
  };//定义复数的相关运算
  Plural x[maxn];// x1[maxn], x2[maxn];
  Plural y[maxn];// y1[maxn], y2[maxn];
  LL ans[maxn];
  int X[maxn];
  int n, len;
public:
  int reverse(int x)
  {
    int ans = 0;
    for (int i = 1, j = n >> 1; j; i <<= 1, j >>= 1) if (x&i) ans |= j;
    return ans;
  }//数字倒序,FFT的初始步骤
  Plural w(double x, double y)
  {
    return Plural(cos(2 * pi * x / y), -sin(2 * pi * x / y));
  }
  bool setx()
  {
    if (scanf("%d", &len) == EOF) return false;
    for (n = 200000; n != low(n); n += low(n));
    for (int i = 0; i < n; i++) { x[i] = Plural(0, 0); ans[i] = 0; }
    for (int i = n = 0; i < len; i++)
    {
      scanf("%d", &X[i]);
      x[X[i]].x += 1.0;
      n = max(n, X[i]);
    }
    for (n = n + n + 1; n != low(n); n += low(n));//这里要注意取值
    return true;
  }
  void fft(Plural*x, Plural*y, int flag)
  {
    for (int i = 0; i < n; i++) y[i] = x[reverse(i)];
    for (int i = 1; i < n; i <<= 1)
    {
      Plural uu = w(flag, i + i);
      for (int j = 0; j < n; j += i + i)
      {
        Plural u(1, 0);
        for (int k = j; k < j + i; k++)
        {
          Plural a = y[k];
          //w(flag*(k - j), i + i) 可以去掉u和uu用这个代替,精度高些,代价是耗时多了
          Plural b = u * y[k + i];
          y[k] = a + b;
          y[k + i] = a - b;
          u = u*uu;
        }
      }
    }
    if (flag == -1) for (int i = 0; i < n; i++) y[i] = y[i] / n;
  }//1是FFT,-1是IFFT,答案数组是y数组
  void solve()
  {
    fft(x, y, 1);
    for (int i = 0; i < n; i++) y[i] = y[i] * y[i];
    fft(y, x, -1);
    for (int i = 0; i < n; i++) ans[i] = (LL)(x[i].x + 0.5);//调整精度
    for (int i = 0; i < len; i++) ans[X[i] + X[i]]--;
    for (int i = 0; i < n; i++) ans[i] = ans[i] >> 1;
    sort(X, X + len);
    LL sum = 0, qur = 0, tot = (LL)len*(len - 1)*(len - 2) / 6;
    for (int i = n, j = len - 1; i&&j; i--)
    {
      for (; (X[j] == i) && j; j--)
      {
        qur += sum - len + 1;
        qur -= (LL)(len - 1 - j)*(len + j - 2) / 2;
      }
      sum += ans[i];
    }
    printf("%.7lf\n", (double)qur / tot);
  }
}fft;

int main()
{
  scanf("%d", &T);
  while (T--)
  {
    fft.setx();
    fft.solve();
  }
  return 0;
}