2019 상하이 경주 ICPC 네트워크 최적화 회선 + C FFT 소규모 폭력

https://nanti.jisuanke.com/t/41400

 

큰 위해, 우리는 오른쪽으로 가치와 B, A와 C, C와 B의 컨벌루션의 배열을 설정 한 후 응답을 컨볼 루션 불법 상황을 뺀 후, N ^ $ 3 $이고

그러나, 각 시간 범위 $ $ 1E5 및 회선 여섯 번마다 한 세트의 복잡성을 수행 할 수 있기 때문에 $ 6 * 2 ^ {CEIL (로그 (2N))} CEIL (로그 (2N)) N = 1E5은 CEIL (X) $는 반올림

테스트 데이터 (100) 설정된 경우, $ 2.8e9 $에 도달 할 수 있습니다

그러나, 우리는 데이터의 5 분의 1이 $ N> $ 1000을 충족 발견

따라서, 소규모 데이터에 대해, 우리는 직접 $의 N ^ 2 $ 폭력을 사용

#INCLUDE <. 비트 / stdc ++ H> 
#DEFINE이 줄게 긴 긴 
#DEFINE 렙 (II, a가, b)에 대한이 (INT II하면 A =; II <= B; ++ II) 
당 #DEFINE (II A, B) 경우 (= INT II의 B]는 II> A = - II) 
std 네임 스페이스를 사용하여 // 헤드 
CONST의 INT maxn = 4e5 + 10 MAXM = 2e6 + (10); 
INF = CONST LL 0x3f3f3f3f, 개조 1E9 + = 7; 
INT의 CASN, N, M, K, 카세 = 1, L, R; 
스페이스 fastio {// @支持读取整数,字符串,输出整数@ 
BOOL isdigit에 (문자 c) {C가 복귀> = 48 && C <= 57} 
CONST의 INT maxsz = 1E7; 
클래스 fast_iostream {공개 : 
  숯불 채널 = get_char (); 
  부울 ENDF = 1, 플래그; 
  숯 get_char () { 
    정적 문자 버퍼 [maxsz] * A = 버퍼 * B = 버퍼; 
    리턴 B에서 == && (b = (a = 버퍼) + FREAD (완충액 1 maxsz 표준 입력), B == a) EOF : *는 ++; 
  }
  서식 <유형 이름 유형> 부울 GET_INT (타입 TMP) { 
    플래그 = TMP = 0; 
    (! isdigit에 (CH3) CH = && EOF) 동안 { '-'플래그 == = CH, CH = get_char ();}; 
    경우 (CH2 == EOF) 반환 ENDF = 0; 
    이렇게 {TMP = CH-48 * 10 + TMP} 동안 (isdigit에 (CH2 = get_char ())); 
    (플래그) TMP = -tmp 경우; 
    1을 반환; 
  } 
  INT의 get_str (숯 *의 STR) { 
    CHAR * TMP = STR; 
    동안 (CH2 == '\ R'|| CH == '\ n'|| CH == ') CH = get_char (); 
    경우 (CH2 == EOF) 창 (ENDF = 0) * TMP = 0; 
    할 {* (TMP ++) = CH, CH = get_char ();} (CH = '\ 연구'를 ch && = '\ n'을 && CH = ''&& CH = EOF!!!!) 동안; 
    * (TMP는 ++) = 0; 
    리턴 (INT) (TMP-STR-1); 
  } 
  fast_iostream & 연산자 >>
  서식 <유형 이름 유형> fast_iostream & 연산자 >> (타입 TMP) {GET_INT (TMP) *이 반환} 
  {복귀 ENDF} 불리언 연산자 ()을 const 
}; 
} fastio :: fast_iostream IO; 

CONST 이중 PI = ACOS (-1.0);
CP 구조체 {이중 X, Y}; 
CP 연산자 * (CP의 A, 및 CP b) {창 {AX * BX-AY * 의해 AX * b.y + (AY)의 *의 BX}} 
CP 연산자 + (CP의 A, 및 CP b) {창 {a.x + BX , a.y의 + 의해}} 
CP의 운용자 (CP의 A, 및 CP b) {창 {AX-BX, AY-의해}} 
클래스 푸리에 {공개 : 
  INT 레브 [maxn, LEN, PW; 
  보이드 INIT (INT 않음) { 
    렌 = 1, PW = 0; 
    반면 (LEN <= N) = 1 << LEN, PW ++; 
    렙 (I 0, 렌-1) 레브 [I] = 0; 
    렙 (I 0, 렌-1) REV [I] = (REV [I >> 1] >> 1) | ((I & 1) << (PW-1)); 
  } 
  공극은 {(CP * A, INT 플래그) 변환
    경우 담당자 LEN (I-1, 0) (난 레브 <[I]) 스왑 (a [i]를, A [REV [I]); 
    대 (INT 중간 = 1, 중간 <LEN, 중간 << = 1) { 
      CP WN = {COS (PI / MID), 플래그 * 죄 (PI / MID)}; 
      대 (INT의 R = 1 << 미드, J = 0; J <LEN, J = R +) { 
        및 CP t = {1,0};  
  CIN >> CASN;
        대 (INT에서 K = 0; K <미드; ++ K는, t는 t의 *의 WN을 =) { 
          CP X = A [J + K, Y = t * A [중간 +의 J + K]; 
          A [J + K] = X + Y, A [J + K + 중간]를 XY =; 
        } 
      } 
    } 
    경우 (플래그 == - 1) 담당자 (I 0, LEN)는 [I]를 .x와 / = LEN; 
  } 
} FFT; 
, A [maxn], B [maxn]을 int로 [maxn] C; 
CP CNTA [maxn] CNTB [maxn] CNTC [maxn]; 
CP의 RESA [maxn]에 resb [maxn] resc [maxn]; 
LL 스마 [maxn] sumb [maxn] sumc [maxn]; 
#DEFINE CIN IO 
INT의 main () {
      렙 (I, 1, N) C의 CIN >> [I]; 
      LL ANS = 1ll * N의 N *의 * 않음;
  (카세 <= CASN) {동안 
    CIN >> N; 
    fft.init (1E5 + 1E5 + 2); 
    경우 (N <= 1000) { 
      렙 (I, 1, N) CIN >> A [I]; 
      렙 (I, 1, N) CIN >> B [I]; 
      정렬 (c + 1, C + N + 1); 
      정렬 (B + 1, B + N + 1); 
      정렬 (A + 1, A + N + 1); 
      렙 (I, 1, 3 [N]) 스마 [I] = 0; 
      렙 (I, 1, N) 렙 (j, 1, N) ++ 스마 [A [I] + B [J]]; 
      렙 (I, 1, 3 [N]) 스마 [I] + = 스마 [I-1]; 
      렙 (I, 1, N) = ans- 스마 [C [I] -1] 
      렙 (I, 1, 2 [N]) 스마 [I] = 0; 
      렙 (I, 1, N) 렙 (j, 1, N) ++ 스마 [A [I] + C [J]]; 
      렙 (I, 1, 2 [N]) 스마 [I] + = 스마 [I-1]; 
      렙 (I, 1, N) = ans- 스마 [B [I] -1] 
      렙 (I, (1), [N]) 스마 [I] = 0; 
      렙 (I, 1, N) 렙 (j, 1, N) ++ 스마 [C [I] + B [J]];
      렙 (I, (1), [N]) 스마 [I] + = 스마 [I-1]; 
      렙 (I, 1, N) = ans- 스마 [A [I] -1] 
      의 printf ( "케이스 # 1 %의 D % LLD \ 없음"카세 ++, ANS); 
      계속하다; 
    }  
    (I, 1, N) {수신 
      CIN >> A [I];
      CNTA [A [I] X ++.; 
    } 
    렙 (I, 1, N) { 
      CIN >> B [I]; 
      CNTB [B [I] X ++.; 
    } 
    렙 (I, 1, n)이 { 
      (CIN) >> (C)의 [I]; 
      CNTC [C [I] X ++.; 
    } 
    fft.transform (CNTA 1) fft.transform (CNTB, 1); fft.transform (CNTC, 1); 
    렙 (I 0, fft.len-1) { 
      RESA [I] = CNTB [I] * CNTC [I]; 
      에 resb [I] = CNTA [I] * CNTC [I]; 
      resc [I] = CNTB [I] * CNTA [I]; 
    } 
    fft.transform (RESA, -1); fft.transform (에 resb, -1); fft.transform (resc, -1); 
    렙 (I, 1 fft.len-1) { 
      스마 [I] = 스마 [I-1] + (LL) (RESA [I] .x와는 + 0.5); 
      sumb [I] = sumb [I-1] + (LL) (에 resb [I] .x를 + 0.5); 
      sumc [I] = sumc에 [I-1] + (LL) (resc [I] .x를 + 0.5); 
    } 
    LL ANS = N * 1ll의 * N 개의 * 않음; 
    렙 (I, 1, N) {
      스마 ans- = [A [I] -1] + sumb [B [I] -1] + sumc [C [I] -1] 
    } 
    의 printf ( "케이스 # % d에 % LLD \ 없음"카세 ++, ANS); 
    렙 (I 0, fft.len) { 
      CNTA [I] = CNTB [I] = CNTC [I] = (CP) {0,0}; 
    } 
  } 
}

 

추천

출처www.cnblogs.com/nervendnig/p/11525240.html