FFT +高速パワー、我々は、最適化の多くを生きるために必要があります
#include <ビット/ STDC ++ H> の#defineが長い長いっ (、II、B)の#define担当者のための(INT II =; II <= bの++ II) (B、II)当たりの#define (INT II = B; II> =; - II)のために (; I I = E [i]は.next int型I = G [X])のための#define fornを(I、X、G、E) #IOのIOSを定義:: sync_with_stdio(偽); cin.tie(0); cout.tie(0) の#define ULL符号なし長い長 の#define Fiの最初 のSEの#define第二 の#define MP make_pair の#define PII対<-1,11,11-> 全ての#define(X)x.begin()、x.end() の#defineショー(X)COUT <<#X << "=" << X << ENDL の#define昭和(a、b)はCOUT << #A << '[' << B << "] =" << [B] << ENDL の#define show2(X、Y)COUT <<#1 X << "=" << X <<」 " <<#yを<<"=" << Y << ENDL "=" << Y << ENDL の#define SHOW3(X、Y、Z)COUT <<#X << "=" << X << " "<<#1 Y <<"=" << Y << " "<<#Z <<"=" << Z <<てendl の#define show4(W、X、Y、Z)COUT << W#<< "=" << W << " "<<#1 X <<"=" << X << " "<<#Y <<"= "<< Y <<" "<<#Z <<"=" << Z << ENDL #define show5(V、W、X、Y、Z)COUT <<#V << "=" << V << " "<< W#<<"= "<< W <<"" <<# X << "=" << X << " "<<#1 Y <<"= "<< Y <<" "<<#Z <<"=" << Z << ENDL の#define showa2(X、 、B)COUT <<#1 X << ":"; COUT << ENDL、担当者(I、a、b)はCOUT << X [i]は<<」」 名前空間stdを使用。 N INT、K。 CONSTダブルPI = ACOS(-1.0)。 構造体CP {ダブルX、Y;}; インラインCP演算子*(CPのA、CPのB){リターン{AX * BX-AY *によって、斧* b.y + AYの*のBX};} インラインCP演算子+(CP Aを、CPのB){リターン{a.x + BX、}によってa.yの+;} インラインCP operator-(CP Aを、CPのB){リターン{AX-BX、AY-によって};} CONST INT MAXL = 1E6 + 10。 int型LA、LB; BOOL [MAXL << 2]。 ブールRET [MAXL << 2]。 LEN = 1、PW = 0。 一方、(LEN <= N)LEN << = 1、PW ++。 クラスフーリエ{パブリック: int型REV [MAXL << 2]、LEN、PW。 INIT(INT n)を無効{ 担当者(I、0、lenの-1)REV [I] = 0; 担当者(I、0、lenの-1)REV [I] =(REV [I >> 1] >> 1)|((I&1)<<(PW-1))。 } のCP C1 [MAXL << 2]、C2 [MAXL << 2]。 CP重量[MAXL << 2]。 ボイドinit_0(INTミリリットル= MAXL){ ため(INTミッド= 1;ミッド<2 * MAXL;中間<< = 1){ // wt.resize(MID * 2 + 1)。 CPのWN1 = {COS(PI / MID)、SIN(PI / MID)}。 質量[中間] =(CP){1,0}。 担当者(J、1、ミッド1)重量[中間+ J] =重量[中間+ J-1] * WN1。 } } ボイド(CP *、INTフラグ){変換 スワップ([I]、[REV [I])(iはREV [I]を<)場合担当者(I、0、lenの-1)。 (;半ば<LEN 1ミッド= INT中間<< = 1)のために{ (INT R =ミッド<< 1、J = 0; J <LEN。 CP WN =重量[中間+ K]。 IF(フラグ== - 1)wn.y = -wn.y。 [J + K +中間]は[J + K] -y [J + K] [J + K] + yは=を=。 } } } 場合(フラグ== - 1)担当者(I、0、lenの-1)[i]を.X / = LEN。 } ボイドFIX1(){一方(LA && RET [LA-1]!) -ラ;} ボイドfix2(){一方(LB && [LB-1]!) - LB;} // @传入整数、进行卷积@ ボイドMUL(BOOL *、ブール* b)は{ INIT(LA + LB)。 担当者(I、0、LA-1)C [I] .X [i]は、C1を= [I] .Y = 0。 担当者(I、LA、lenの-1)C1 [i]は.X = C1 [i]が.Y = 0。 担当者(I、0、LB-1)C2 [i]は.X = bの[I]、C2 [i]は.Y = 0。 担当者(I、LB、lenの-1)C2 [i]は.X = C2 [i]が.Y = 0。 (C2,1)変換;(C1,1)変換。 担当者(I、0、lenの-1)C [I] = C1の[I] * C2 [i]は、 変換(C1、-1); ラ= LEN。 担当者(I、0、lenの-1)[I] = C1の[I] .X> = 0.5。 FIX1(); } ボイドSQR(BOOL * A){ INIT(2×LB)。 担当者(I、0、LB-1)C [I]・X [i]は、C1を= [I] .Y = 0。 担当者(I、LB、lenの-1)C1 [i]は.X = C1 [i]が.Y = 0。 (C1,1)変換。 担当者(I、0、lenの-1)C [I] = C1の[I] * C1 [i]は、 変換(C1、-1); ポンド= LEN。 担当者(I、0、lenの-1)[I] = C1の[I] .X> = 0.5。 fix2(); } ボイドPOW(int型K){ FIX1();ラ= 1、RET [0] = 1; 一方、(K){ IF(K&1)MUL(RET、A)。 SQR(A)。 K >> = 1。 } } } FFT。 int型S [2000]; INTメイン(){ IOS :: sync_with_stdio(偽); cin.tie(0)。 CIN >> N >> K。 以下のために(INT i = 1; iが<= N; iは++){ CIN >> S [i]は、 [S [I] = 1。 } ソート(S + 1、S + 1個の+ N)。 fft.init_0(S [N] * K + 1)。 ポンド= 1001; fft.pow(K)。 INT LEN =分(LA、S [N] * K + 1)。 以下のために(iはK = int型、iがLEN <; iは++)IF(RET [i])とCOUT << I <<」「。 }