제목 설명
$ $ N 자리의 십진수 X와 Y를 X의 * y를 찾을 두 감안할 때 (참조 루오 밸리 P1919를 )
분석
가정 FFT / NTT를 배웠습니다.
$ X = 10 $에 해당하는 특별한 경우 정밀 곱셈을 제외하고 다항식 곱셈.
예를 들어, N = 111 (123)가 시크 * 3
$$ 123 = X ^ 2 + 3 + 2 × $$
$$ 111 = X ^ 2 + X + 1 $$
$$ \ 시작 {123} 배향 * 111 = (X ^ 2 + 3 + 2 ×) (X ^ 2 + X + 1) = \\ 및 X ^ 4 + 3X ^ 3 + (6X) ^ 2 + 3 + 5 배 \ \ = 13,653 및 단부 \ {} 배향 $$
코드 :
#INCLUDE <비트 / stdc ++ H.> #DEFINE의 RG 등록 하여 스페이스 성병; 타입 정의 긴 긴 LL; CONST INT 개조 = 998,244,353 , g = 3 ; CONST의 INT maxn 6E4 + = 10 ; 인라인 INT qpow ( INT (X), INT의 K) { INT ANS = 1 ; 하면서 (K) { 경우 (K & 1 ) ANS = (LL)가 ans와 * X % 개조; 엑스= (LL) * X X %의 개조, K >> = 1 ; } 반환 ANS; } 인라인 INT의 모듈 ( INT의 X, INT의 Y) { X + = Y; 만약 (x> = 개조) X - = 개조; 반환 X를; } INT의 브 [ 4 * maxn]; 인라인 공극 NTT ( INT의 *를 t, INT 임 INT 타입) { 대 (RG의 INT에 I = 0 ; I <LIM; ++ I) 경우 (전 < 레브 [I]) 스왑 (t [I], t [REV [I]); 대 (RG INT I = 1 ; I <LIM 나는 << = 1 ) { INT GN = qpow (g (mod- 1 ) / (I << 1 )); 경우 (유형 == - 1 ) GN = qpow (GN, mod- 2 ); 대 (RG INT J = 0 ; J <LIM] = J + (I << 1 )) { INT의 GI = 1 ; 대 (RG의 INT를 K = 0, K <I; ++ K, GI = (LL) 위장관 *의 GN의 %의 개조) { INT (X) = t [J + K, Y = (LL) 위장관 *를 t [J + I + K] % 개조; t [J + K = 모듈 (X, Y); t [J I + K +] = 모듈 (X, mod- Y); } } } 경우 (유형 == - 1 ) { INT INV = qpow (LIM, mod- 2 ); 대 (RG의 INT I = 0 ; I <LIM; ++ I) t [I] = (LL) t [i]는 INV * % 개조; } } INT X [ 4 * maxn], Y [ 4* MAXN] 인라인 공극 MUL ( INT * X, INT * Y, INT N-, INT m) { memset 함수 (X-, 0 , sizeof의 (X-)) 가 memset합니다 (Y, 0 , sizeof의 합니다 (Y)); INT 임 = . (1) , L = 0 , // 0 작성해야 = L은, 디폴트 값은 로컬 변수 않을 수도 0 그동안 (LIM <= N-m의 +) = 임 << 1. , L ++; // 임보다 (N + m)의 (2)의 전력은 그 최대 4 배의 공간 을위한 ( int로 I = 0 ; I ++는, I는 림을 <) 계 [I] = (계 [I >> . 1] >> 1 ) | ((I & 1 ) << (L - 1 )); 대 (RG INT I = 0 ; I <LIM; I ++) X [I]의 X = [I], Y [I] = Y [I]; NTT (X, LIM, 1 ); NTT (Y, LIM, 1 ); 대 (RG의 INT에 I = 0 ; I <LIM; I ++) X [I] = (LL) X [I] * Y [i]를 % 개조; NTT (X, LIM, - 1 ); 대 (RG의 INT에 I = 0 ; I <LIM; I ++) × [I] =를 X [I]; } int로 N; int로 A [ 4 * maxn, B의 [ 4* maxn]; 문자 S [maxn]; INT 의 main () { 는 scanf ( " %의 D ' , N); scanf와 ( " %의 S ' , S); 위한 ( int로 I = 0 A [I]가 S [N- 내가 ++; i가 N <) 1 - -i] ' 0 '을 ; scanf와 ( " %의 S ' , S); 위한 ( int로 I = 0 ; I <N은, 내가 ++) [I] =에서 S [N- B 1 -i] - ' 0 ' ; MUL (A, B, N); // 경우 (나는 2 * N을 <; I = 0 int로 난 ++)에서 printf ( "%의 D"는 [I]); // 의 printf ( "\ n")를; INT의 TMP = 0 ; // 进位을 위해 ( int로 난 = 0 ; i가 < 2 * N; 내가 ++) // { A [내가] = A [i]는 + TMP; TMP가 = A [I] / 10 ; A [I]는 A [i]는 (%) = 10 ; } // 대해 (나는 2 * <N; I = 0 int로 난 ++)에서 printf ( "%의 D"는 [I]); // 의 printf ( "\ n")를; 부울 플래그 = 진정한 ; 대한 (INT I = 2 * N-; I는> = 0 , 난 -) // 선두 제로 제거 차 역방향 출력 { IF (플래그 && A의이 [I]를 == 0 ) 계속 ; 에서 printf ( " %의 D를 " , A [I] ) 플래그 = 거짓 ; } 반환 0 ; }