【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 }