The implementation of FFT is quite complicated. We started to use vector and found that the space was too large. We changed it to an array or super. After deleting a few, it timed out again.
The sin cos function has been called too many times. If it is changed to multiplication, it still times out.
Finally, we optimized the division and modulo operations in the FFT, and finally passed.
Pitfall: 3843 Ms. The minimum time is only 671 Ms. I suspect this is not the same algorithm .. This is why the Mao gap is so big.
# Pragma comment (linker, "/Stack: 102400000,102400000 ") # include <iostream> # include <vector> # include <algorithm> # include <cstdio> # include <queue> # include <stack> # include <string> # include <map> # include <set> # include <cmath> # include <cassert> # include <cstring> # include <iomanip> # include <ctime> using namespace STD; # ifdef _ win32typedef _ int64 i64; # define out64 "% i64d \ n" # define in64 "% i64d" # elsetypedef long i64; # de Fine out64 "% LLD \ n" # define in64 "% LLD" # endif/************ for topcoder by zz1215 ****** * ************/# define foreach (C, itr) for (_ typeof (c ). begin () itr = (c ). begin (); itr! = (C ). end (); itr ++) # define for (I, a, B) for (INT I = (a); I <= (B); I ++) # define ff (I, A) for (INT I = 0; I <(a); I ++) # define FFD (I, a, B) for (INT I = (a); I >= (B); I --) # define s64 (a) scanf (in64, & A) # define SS () scanf ("% d", & A) # define LL (A) (a) <1) # define RR (A) (a) <1) + 1) # define Pb push_back # define pf push_front # define x first # define y second # define Cl (q) while (! Q. empty () Q. pop () # define mm (name, what) memset (name, what, sizeof (name) # define MC (a, B) memcpy (A, B, sizeof (B) # define max (A, B) (a)> (B )? (A) :( B) # define min (A, B) (a) <(B )? (A) :( B) # define read freopen ("in.txt", "r", stdin) # define write freopen ("out.txt", "W", stdout) const int INF = 0x3f3f3f; const i64 inf64 = 0x3f3f3f3f3f3fll; const double oo = 10e9; const double EPS = 10e-9; const double Pi = ACOs (-1.0); const int maxn = 401111; struct Complex {double A, B; complex (double _ A = 0.0, double _ B = 0.0): A (_ A), B (_ B) {} complex operator + (const complex & C) const {return complex (A + C. a, B + C. b);} complex operator-(const complex & C) const {return complex (a-c. a, B-c. b);} complex operator * (const complex & C) const {return complex (A * C. a-B * C. b, A * C. B + B * C. a) ;}}; complex W [maxn]; int ID [maxn]; // change idcomplex FAC [maxn]; // vector acomplex FBC [maxn]; // vector bcomplex fabc [maxn]; // vector A * bvoid make_id (int id [], int Len) {for (INT step = Len/2; Step> = 1; step> = 1) {for (INT it = Len/step/2; it <Len/step; it ++) {ID [it] = ID [it-len/step/2] + step; }}} void DFT (complex a [], complex TC [], complex W [], int ID [], int Len) // transform function a, temporary function TC, plural matrix W, length Len {for (INT I = 0; I <Len; I ++) {TC [I] = A [ID [I];} int temp, TW; For (INT step = 1; Step <= Len/2; Step <= 1) {for (INT x = 0; x <Len; x + = Step * 2) {temp = Len/(Step * 2); Tw = 0; for (INT it = x; it <X + step; it ++) {A [it] = tc [it] + Tc [It + step] * W [TW]; TW + = temp;} For (INT it = x + step; it <X + step * 2; it ++) {A [it] = tc [it-step] + Tc [it] * W [TW]; TW + = temp ;}} for (INT I = 0; I <Len; I ++) {TC [I] = A [I] ;}} void convolution (complex a [], complex B [], complex C [], int Len) // convolution {for (INT I = 0; I <Len; I ++) {C [I] = A [I] * B [I];} void divide (Complex C [], int Len) {for (INT I = 0; I <Len; I ++) {C [I]. a/= Len ;}} void FFT (complex a [], complex B [], complex C [], int ID [], complex W [], int Len) {make_id (ID, Len); double ang = double (2.0 * PI)/double (LEN); W [1] = complex (COS (ANG ), sin (ANG); W [0] = complex (1, 0); For (INT x = 2; x <Len; X ++) {W [x] = W [1] * W [X-1];} DFT (A, C, W, ID, Len); DFT (B, c, W, ID, Len); convolution (a, B, c, Len); W [1] = complex (COS (-Ang), sin (-Ang )); for (INT x = 2; x <Len; X ++) {W [x] = W [1] * W [X-1];} DFT (C,, w, ID, Len); divide (C, Len);} void tocomplex (int A [], complex Ca [], int Len) {for (INT I = 0; I <Len; I ++) {Ca [I] = complex (A [I], 0) ;}} void toint (i64 A [], COMPLEX AC [], int Len) {for (INT I = 0; I <Len; I ++) {A [I] = i64 (AC [I]. A + 0.5) ;}} int N; int Branche [maxn]; int FX [maxn]; i64 res [maxn]; Double Start () {int temp = 0; for (INT I = 1; I <= N; I ++) {temp = max (temp, Branche [I]);} temp + = 10; int Len = 1; while (LEN <temp) {Len <= 1;} Len <= 1; for (INT I = 0; I <Len; I ++) {FX [I] = 0 ;}for (INT I = 1; I <= N; I ++) {FX [Branche [I] ++ ;} tocomplex (FX, FAC, Len); tocomplex (FX, FBC, Len); FFT (FAC, FBC, fabc, ID, W, Len); toint (Res, fabc, len); For (INT I = 1; I <= N; I ++) {res [2 * Branche [I] --;} For (INT I = 0; I <Len; I ++) {res [I] >>=1 ;}for (INT I = 1; I <Len; I ++) {res [I] + = res [I-1];} i64 num = 0; For (INT I = 1; I <= N; I ++) {num + = res [Branche [I];} i64 tot = (i64) N * (N-1) * (N-2); TOT/= 6; double ans = double (Num)/double (TOT); ans = 1.0-ans; return ans;} int main () {int t; CIN> T; while (t --) {CIN> N; For (INT I = 1; I <= N; I ++) {// CIN> Branche [I]; SS (Branche [I]);} printf ("%. 7lf \ n ", start ();} return 0 ;}