設參與運算的多項式最高次數是n,那麼多項式的加法,減法顯然可以在o(n)時間內計算。
所以我們關心的是兩個多項式的乘積。樸素的方法需要o(n^2)時間,並不夠優秀。
考慮優化。
方案一:分治乘法。
對於多項式x,y,假設各有2m項,(即最高次數是2m-1)
x,y分別可以用兩個含m項的多項式來表示,即:
則由此可見,為了計算xy,只需計算出ac, (a+b)(c+d), bd,然後用多項式加減法求得xy即可。
設含有m項的多項式相乘的時間為t(m)
則於是容易算出時間複雜度是
,約等於
以上方法的優點在於,**難度低,思維難度低,多項式係數任意,對運算沒有任何限制。
缺點在於:太慢了!
方案二:fft / ntt
這種方法除了快之外,沒有任何優點。但仍是一種好方法。
fft的詳細推導不再描述,這裡只是簡單的總結。
對於多項式乘法,有一種思路,
a. 是先從係數表示法轉換為點值表示法,
b. 然後乘起來(得到乘積式的點值表示法),
c. 最後從點值表示法轉變回係數表示法。
對於操作a,很容易做到o(n^2),
對於操作b,很容易做到o(n),
對於操作c,用高斯消元可以做到o(n^3),用拉格朗日插值法可以做到o(n^2)。
fft則是利用了單位根的性質,將操作a和操作c優化到了o(nlogn)。
雖然在複數域中永遠存在單位根,但是容易出現精度問題。
ntt並沒有用複數域的單位根。
當某兩個多項式相乘,係數對某一模數取模的時候,必須存在2^k次(2^k>=2n)單位根,且必須存在2的逆元。
當模數p是形如 998244353 的質數時,998244353 = 7 × 17 × 2^23 + 1,( 2^k | phi(p) )
設p的原根是g,則模p意義下,2^k次單位根是
。當模數並不是滿足要求的模數,我們可以知道,一次多項式乘法的結果,每一位上的數不超過n*p*p。
我們可以取多個不同的ntt模數,使得它們的乘積大於n*p*p。對每乙個ntt模數做一次多項式乘法,最後用中國剩餘定理計算即可。
我們定義多項式a的乘法逆元b,滿足a*b=1。
多項式求逆能解決多項式除法等一系列問題,因為x/y=x*y的逆元。
我們首先證明,多項式a存在乘法逆元的充要條件是a的常係數存在逆元。
必要性顯然,因為a的常數項*b的常數項=1。
由此,我們可以求出b的常數項,接著推出一次項係數,二次項係數...
所以乘法逆元存在且唯一,充分性同樣顯然。
為了求逆元,一種方法是o(n^2),即先求常數項,再推出一次項係數,繼續推完整個多項式。
還有一種用o(nlogn)時間計算乘法逆元的方法,
先求出a(x)的常數項的逆元b,初始化b(x)=b,則
多項式乘法運算 NTT 數論變換 實現
多項式乘法 之前用fft交了乙個無限wa,懷疑是精度有問題然後就轉向ntt。關於fft和ntt力薦這兩篇吼文章,講得太吼了 塔萌講得很好了,我就存個這個模板。include include include include include include include include include...
FFT與多項式乘法
鑑於網上關於fft作用的文章並不少,這裡盡量少說廢話,直接說如何理解和具體實現 關於多項式乘法,通常是用係數乘積的方式,這樣的時間複雜度是o n 2 n為多項式項數。這可以滿足大多數的乘法需求,然而當位數大於1000時,此法用起來就顯得捉襟見肘 於是我們便有了偉大的fft來解決這個問題 係數表示法 ...
FFT與多項式乘法
係數表示法 即平時看到的多項式 i 0 n 1 a i x i 點值表示法 乙個最高次為n 1次的多項式f x 可以表示為n個其影象上點 x,y 例如2x 2 3x 1可以表示為 0,1 1,6 2,15 兩種方法可以互相轉換,而點值表示法下兩多項式相乘是非常方便的,只要將同乙個x對應的兩式y值相乘...