3513: [MUTC2013]idiots
3513: [MUTC2013]idiots
分析:
考虑求不合法的方案数,可以枚举一条最大的边,另外两条边要求长度和小于等于这条边。
设dp[i]表示任选两条,长度为和为i的方案数,这是一个卷积,FFT优化。然后维护一个前缀和。
代码:
#include<cstdio> #include<algorithm> #include<cstring> #include<iostream> #include<cctype> #include<cmath> #include<set> #include<map> #include<vector> #include<queue> #include<bitset> using namespace std; typedef long long LL; inline int read() { int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1; for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f; } const int N = 270005; const double Pi = acos(-1.0); struct Com{ double x, y; Com() {} Com(double _x,double _y) { x = _x, y = _y; } }A[N]; Com operator + (const Com &A,const Com &B) { return Com(A.x + B.x, A.y + B.y); } Com operator - (const Com &A,const Com &B) { return Com(A.x - B.x, A.y - B.y); } Com operator * (const Com &A,const Com &B) { return Com(A.x * B.x - A.y * B.y, A.x * B.y + A.y * B.x); } int rev[N], cnt[N], dp[N]; void FFT(Com *a,int n,int ty) { for (int i = 0; i < n; ++i) if (i > rev[i]) swap(a[i], a[rev[i]]); Com w, w1, u, t; for (int m = 2; m <= n; m <<= 1) { w1 = Com(cos(2 * Pi / m), ty * sin(2 * Pi / m)); for (int i = 0; i < n; i += m) { w = Com(1, 0); for (int k = 0; k < (m >> 1); ++k) { u = a[i + k], t = w * a[i + k + (m >> 1)]; a[i + k] = u + t, a[i + k + (m >> 1)] = u - t; w = w * w1; } } } } void solve() { int n = read(), Mx = 0, len = 1, lg = 0; for (int x, i = 1; i <= n; ++i) x = read(), cnt[x] ++, Mx = max(Mx, x); while (len <= Mx + Mx) len <<= 1, lg ++; for (int i = 0; i < len; ++i) { rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << (lg - 1)); A[i] = Com(cnt[i], 0); } FFT(A, len, 1); for (int i = 0; i < len; ++i) A[i] = A[i] * A[i]; FFT(A, len, -1); for (int i = 0; i < len; ++i) dp[i] = (A[i].x / (double)len + 0.5); LL ans = 0, now = 0, tot = 1ll * n * (n - 1) * (n - 2) / 6; for (int i = 0; i < len; ++i) { now += dp[i]; if (i % 2 == 0) now -= cnt[i / 2]; ans += 1ll * now * cnt[i]; } ans /= 2; printf("%.7lf\n", (1.0 - 1.0 * ans / (double)tot)); memset(cnt, 0, sizeof(cnt)); for (int i = 0; i < len; ++i) A[i].x = A[i].y = dp[i] = rev[i] = 0; } int main() { for (int T = read(); T--; solve()); return 0; }