這可以在O(n log n)
的時間內完成對任意P
和n
程度Q
。更確切地說,這可以在M(n)
中完成,其中M(n)
是多項式乘法的複雜度,其本身可以在O(n log n)
中完成。
首先,第一個n
系列擴展的術語可以簡單地看作是n-1
的多項式。
假設您有興趣在P(x)/Q(x)
系列擴展的第n
條款。存在如上定義的計算M(n)
時間內的Q
的倒數的算法。
逆T(x)
的Q(x)
滿足T(x) * Q(x) = 1 + O(x^N)
。即T(x) * Q(x)
恰恰是1
加上一些誤差項,其係數都在我們感興趣的第一項術語後面,所以我們可以放棄它們。
現在P(x)/Q(x)
只是P(x) * T(x)
,這只是另一個多項式乘法。
您可以在我的開源庫Altruct中找到一個計算上述反轉的實現。請參閱series.h文件。假設你已經有了一個計算兩個多項式乘積的方法,那麼計算倒數的代碼約爲10行(分而治之)。
實際算法如下: 假設Q(x) = 1 + a1*x + a2*x^2 + ...
。如果a0
不是1
,則可以簡單地將Q(x)
及其後的逆T(x)
與a0
分開。 Asume,在每一步你有L
條款的逆使Q(x) * T_L(x) = 1 + x^L * E_L(x)
一些錯誤E_L(x)
。最初爲T_1(X) = 1
。如果你在上面插入這個,你將得到Q(x) * T_1(x) = Q(x) = 1 + x^1 * E_1(x)
對於一些E_1(x)
這意味着這適用於L=1
。現在讓我們在每一步加倍L
。您可以從上一步獲得E_L(x)
作爲E_L(x) = (Q(x) * T_L(x) - 1)/x^L
,或執行方式,只需刪除產品的第一個L
係數。然後,您可以將上一步中的T_2L(x)
計算爲T_2L(x) = T_L(x) - x^L * E_L(x) * T_L(x)
。錯誤將是E_2L(x) = - E_L(x)^2
。現在讓我們來檢查誘導步驟是否成立。
Q(x) * T_2L(x)
= Q(x) * (T_L(x) - x^L * E_L(x) * T_L(x))
= Q(x) * T_L(x) * (1 - x^L * E_L(x))
= (1 + x^L * E_L(x)) * (1 - x^L * E_L(x))
= 1^2 - (x^L * E_L(x))^2
= 1 + x^2L * E_2L(x)
Q.E.D.
我敢肯定這是不可能計算多項式除法比乘法更高效,你可以在下表中看到,該算法比一次乘法慢了3次:
n mul inv factor
10^4 24 ms 80 ms 3,33x
10^5 318 ms 950 ms 2,99x
10^6 4.162 ms 12.258 ms 2,95x
10^7 101.119 ms 294.894 ms 2,92x
@ DavidEisenstat謝謝,這簡化了任務。但是我怎樣才能找到長分裂的'1/Q(x)'?我認爲與分工我只找到商和餘數。 – Somnium
@DavidEisenstat謝謝!避免分離也會加速事情,因爲乘法將是* O(n * m)*,其中n - 項的數量,m - 度。順便說一句,我不會理解爲什麼我的答案被標記爲過於寬泛,它需要一個特定的算法。 – Somnium
@DavidEisenstat你去了:)也許我們應該啓動一個關於meta的[算法]狀態的話題。對於是否將這些問題提交給CS –