多項式逆多項式除算が基礎であるあなたは、多項式逆ない場合は、参照してくださいここに
問題:2つの多項式$ F(x)は$(数がnである)、$ G(x)は$(数をmとする)、2つの多項式の$ Qの和(X)$と$ R(X)$、満足を与えられます$ F(X)= G(x)はQ(x)+ R(X)$、すべての操作は意味で998 244 353ダイ行います
式の押し出さ:
$ F(X)= G(x)はQ(x)+ R(x)は$
$ \ FRAC {1} {X} $代替の$ X $で、与えるために:
$ F(\ FRAC {1} {X})= G(\ FRAC {1} {X})Q(\ FRAC {1} {X})+ R(\ FRAC {1} {X})$
与えるために$ X ^ {N} $によって両側。
$ X ^ {n}はF(\ FRAC {1} {X})= X ^ {M} G(\ FRAC {1} {X})は、x ^ {NM} Q(\ FRAC {1} {X}) + X ^ {n}はR(\ FRAC {1} {X})$
$ F(X)$は、Nの数、(X)$ $ Gは、m倍である場合に式$ F(X)= G(x)はQ(x)+ R(X)$分析し、それを見ることができます$ Q(x)は$(x)は$ M-1の数を超えない$ NM $、$ Rの数であります
そして、最初の引数の逆を取ると、その後の最大回数によって多項式の元多項式係数と同等の構造は正反対です!
也即若$ F(X)= \ sum_ {i = 0} ^ {n}はA_ {I} X ^ {I} $、则$ X ^ {n}はF(\ FRAC {1} {X})= \ sum_ {i = 0} ^ {n}はA_ {NI} X ^ {I} $
我々は、x ^ {N} F(\ FRAC {1} {X})= \ sum_ {i = 0} ^ {n}はA_ {NI} X ^ {I} = F ^ {T}(X)$ $を注意します
次いで、上記の式は、$ F ^ {T}(X)= G ^ {T}(X)Q ^ {T}(X)+ R ^ {T}(X)$に簡略化することができます
係数はアイテム$ 0で多項式$(N-M + 1)の前には、$ R ^ {T}(X)$見出すことができます!
そこで、$ MOD $ $ X ^ {N-M + 1} $センスで、この式を直ちに導出することができる場合。
$ F ^ {T}(X)\当量G ^ {T}(X)Q ^ {T}(X)$($ MOD $ $ X ^ {N-M + 1} $)
転置そうだったという。
$ Q ^ {T}(X)\当量\ FRAC {F ^ {T}(X)} {G ^ {T}(X)} $($ MOD $ $ X ^ {N-M + 1} $)
これは、その後、元の式に基づいて、$ Q(x)は$を、決定し、我々が得ます:
$ R(X)= F(X)-G(x)はQ(x)は$
$ R(x)をしても出て$
書式#include <cstdioを> する#include <cmath> の#include <CStringの> の#include <cstdlib> 書式#include <iostreamの> の#include <アルゴリズム> 書式#include <キュー> の#include <スタック> に#define LL長い長い 使って 名前空間はstd; constの LLモード= 998244353 ; INT [(に1 << 20)+ 5 ]。 INTのN、M。 LL FF [ 100005 ] GG [ 100005 ]、F [ 100005 ]、G [ 100005 ]、Q [100005 ]、GF [ 100005 ]。 構造体ノード { LLのG [ 100005 ]。 int型のlen; 今}ラス、。 LLのpow_mul(LLのX、LLのY) { LL RET = 1 。 一方、(Y) { 場合(Y&1)RET = RET * X%のモード。 X = X * X%のモード、Y >> = 1 。 } 戻りRET。 } ボイド NTT(LL *、INT LEN、int型K) { ため(INT I = 0;)私は++; iがLEN < 場合(iは< ([i])と交換する[I])[I]に]。 以下のために(int型 i = 1 ; iがLEN <; I << = 1 ) { LL W0 = pow_mul(3、(モード- 1)/(I << 1 ))。 用(INT J = 0 ; J <LEN; J + =(I << 1 )) { W LL = 1 。 用(INT O = 0 ; 0 <I; O ++、W = W * W0%のモード) { LLのW1= [J + O]、W2 = [J + O + I] *%wのモード。 [J + O] =(W1 + W2)%のモード、[J + O + I] =((W1-W2)%モード+モード)%のモード。 } } } もし(K == - 1 ) { LL INV = pow_mul(LEN、モード- 2 )。 以下のために(int型 i = 1 ; iが<(LEN >> 1); iは++)スワップ([I]、[len- I])。 以下のために(int型 iは= 0 ; iがLEN <; I ++)は、[I] [I] * INV%の= モード。 } } [(LL 1 << 20)+ 5 ]、Bは[(1 << 20)+ 5 ]、[(C 1 << 20)+ 5 ]。 ボイド解く(INTのDEP) { 場合(DEP == 1 ) { now.g [ 0 ] = pow_mul(G [ 0 ]、モード- 2 )。 now.len = 1 。 ラス = 今; 返します。 } INT NXT =(DEP + 1)/ 2 。 (NXT)を解きます。 INT LIM = 1、L =0 ; 一方、(LIM <= 2 * DEP)LIM << = 1、L ++ 。 以下のために(int型私= 0 ;私は++;私は<LIM)への[i]を=((へ[I >> 1 ] >> 1)|((I&1)<<(1- 1 ))); 以下のために(int型 i = 0 ; iは<LIM; iは++)[I] = bの[I] = 0 ; 以下のために(int型 i = 0 ; iはDEPを<; iは++)[I] = G [i]は、 以下のために(int型 i = 0 ; iはNXTを<; iは++)B [I] = las.g [I]。 NTT(、LIM、1)、NTT(B、LIM、1 )。 以下のために(int型 i = 0 ; I <LIM; iは++)C [i]は[i]は* B [i]は%モード*のB [I]%の= モード。 NTT(C、LIM、 - 1 )。 now.len = DEP。 以下のために(int型 i = 0 ; iはDEP <; iは++)now.g [I] =((2 * las.g [I] -c [I])%モード+モード)%のモード。 ラス = 今; } ボイド MUL(LL * A、LLの*のB、INT LEN) { int型 LIM = 1、L = 0 。 一方、(LIM <= 2 * LEN)LIM << =1、L ++ 。 以下のために(int型 I = 1 ;私は++;私は<LIM)への[i]を=((へ[I >> 1 ] >> 1)|((I&1)<<(1- 1 ))); 以下のために(int型 i = 0 ; iは<LIM; iは++)[I] = bの[I] = 0 ; 以下のために(int型 i = 0 ; iがLEN <; iは++)[I] = A [i]が、B [I] = B [i]は、 NTT(LIM、1)、NTT(B、LIM、1 )。 以下のために(int型 i = 0 ; I <LIM; iは++)C [I] = [I] * B [I]%のモード。 NTT(C、LIM、 -1 ); } int型のmain() { scanf関数(" %D%dの"、&N、&M)。 以下のために(int型 i = 0 ; iが<= N; iは++)scanf関数を(" %のLLD "、&FF [i])と、F [NI] = FF [I]。 以下のために(int型私= 0 ; I <= M; I ++)はscanf関数(" %のLLD "、&GG [i])と、G [M] = GG [I]。 用(int型 I = N-M + 2 G [I] =; I <= M I ++)は0 。 以下のために(int型 iは= N-M + 1 F [I] = iは++; iがn = <)0 ; (N解決 -m + 1 )。 以下のために(int型 i = 0 ; I <=ナノメートル; iは++)GF [I] = now.g [I]。 MUL(F、GF、N -m + 1 )。 以下のために(int型私= 0 ; I <= NM; I ++)はQ [I] =のC [I]を、 以下のために(int型 i = 0 ; I <= NM; I ++)はQ [i]は= Cの[NM- I]を、 用(int型 iは= 0のprintf(; I <= NM I ++)は、 " %のLLD " 、Q [I])。 printf(" \ nを" ); MUL(Q、GG、MAX(M + 1、N-M + 1 ))。 以下のために(int型 i = 0 ; iがmを<; iは++)のprintf(" %のLLD "、((FF [I] -c [I])%モード+モード)%のモード)。 printf(" \ nを" ); リターン 0 ; }