【FFT】HDU 4609 3-idiots

通道:http://acm.hdu.edu.cn/showproblem.php?pid=4609

题意:n条边长,求任选3条能组成三角形的概率。

思路:求出res后,减去一大一下,减去都大于它的边,减去该边和其他边组成的方案。

代码:

 

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <cmath>
  4 #include <algorithm>
  5 
  6 typedef long long ll;
  7 
  8 const int MAX_N = 100007;
  9 const int MAX_M = 100007;
 10 const double PI = acos(-1.0);
 11 
 12 struct Complex {
 13     double r, i;
 14     Complex(double _r, double _i) {
 15         r = _r;
 16         i = _i;
 17     }
 18     Complex operator + (const Complex &c) {
 19         return Complex(c.r + r, c.i + i);
 20     }
 21     Complex operator - (const Complex &c) {
 22         return Complex(r - c.r, i - c.i);
 23     }
 24     Complex operator * (const Complex &c) {
 25         return Complex(c.r * r - c.i * i, c.r * i + c.i * r);
 26     }
 27     Complex operator / (const int &c) {
 28         return Complex(r / c, i / c);
 29     }
 30     Complex(){}
 31 };
 32 
 33 
 34 namespace FFT {
 35     int rev(int id, int len) {
 36         int ret = 0;
 37         for(int i = 0; (1 << i) < len; ++i) {
 38             ret <<= 1;
 39             if(id & (1 << i)) ret |= 1;
 40         }
 41         return ret;
 42     }
 43     Complex A[MAX_M << 2];
 44     void FFT(Complex *a, int len, int DFT) {
 45         for(int i = 0; i < len; ++i) A[rev(i, len)] = a[i];
 46         for(int s = 1; (1 << s) <= len; ++s) {
 47             int m = (1 << s);
 48             Complex wm = Complex(cos(DFT * 2 * PI / m), sin(DFT * 2 * PI / m));
 49             for(int k = 0; k < len; k += m) {
 50                 Complex w = Complex(1, 0);
 51                 for(int j = 0; j < (m >> 1); j++) {
 52                     Complex t = w * A[k + j + (m >> 1)];
 53                     Complex u = A[k + j];
 54                     A[k + j] = u + t;
 55                     A[k + j + (m >> 1)] = u - t;
 56                     w = w * wm;
 57                 }
 58             }
 59         }
 60         if(DFT == -1) for(int i = 0; i < len; ++i) A[i] = A[i] / len;
 61         for(int i = 0; i < len; i++) a[i] = A[i];
 62     }
 63 };
 64 
 65 int n;
 66 int a[MAX_N], num[MAX_N << 2];
 67 ll sum[MAX_N << 2], res[MAX_N << 2];
 68 Complex X[MAX_N << 2];
 69 
 70 int main() {
 71     int T;
 72     scanf("%d", &T);
 73     while (T-- > 0) {
 74         scanf("%d", &n);
 75         int up = 0;
 76         for (int i = 0; i < n; ++i) scanf("%d", &a[i]), up = std::max(up, a[i]);
 77         memset(num, 0, sizeof num);
 78         for (int i = 0; i < n; ++i) ++num[a[i]];
 79         
 80         ++up;
 81         int len = 1;
 82         while (len < up) len <<= 1; len <<= 1;
 83         for (int i = 0; i < up; ++i) 
 84             X[i] = Complex(num[i], 0);
 85         for (int i = up; i < len; ++i) 
 86             X[i] = Complex(0, 0);
 87         FFT::FFT(X, len, 1);
 88     //    for (int i = 0; i < len; ++i) printf("%lf %lf\n", X[i].r, X[i].i);
 89         
 90         for (int i = 0; i < len; ++i) 
 91             X[i] = X[i] * X[i];
 92         FFT::FFT(X, len, -1);
 93         for (int i = 0; i < len; ++i)
 94             res[i] = (ll)(X[i].r + 0.5);
 95     //    for (int i = 0; i < len; ++i) printf("%d ", res[i]); puts("");
 96         
 97         
 98         
 99         for (int i = 0; i < n; ++i) {
100             --res[a[i] + a[i]];
101         }
102         for (int i = 0; i < len; ++i) {
103             res[i] >>= 1;
104         }
105         sum[0] = res[0];
106         for (int i = 1; i < len; ++i) {
107             sum[i] = sum[i - 1] + res[i];
108         }
109         ll ans = 0;
110         for (int i = 0; i < n; ++i) {
111             ans += sum[len - 1] - sum[a[i]];
112             ans -= n - 1, ans -= (ll) i * (n - 1 - i);
113             ans -= (ll) (n - 1 - i) * (n - 2 - i) / 2;
114         }
115         ll tot = (ll) n * (n - 1) * (n - 2) / 6;
116         printf("%.7f\n", 1. * ans / tot);
117     }
118     return 0;
119 }
View Code

 

posted @ 2015-07-24 15:54  mithrilhan  阅读(181)  评论(0编辑  收藏  举报