今天來聊一道與數**算有關的題目,leetcode 372 題 super pow,讓你進行巨大的冪運算,然後求餘數。
int superpow(int a, vector& b);
要求你的演算法返回冪運算 a^b 的計算結果與 1337 取模(mod,也就是餘數)後的結果。就是你先得計算冪 a^b,但是這個 b 會非常大,所以 b 是用陣列的形式表示的。
這個演算法其實就是廣泛應用於離散數學的模冪演算法,至於為什麼要對 1337 求模我們不管,單就這道題可以有三個難點:
一是如何處理用陣列表示的指數,現在 b 是乙個陣列,也就是說 b 可以非常大,沒辦法直接轉成整型,否則可能溢位。你怎麼把這個陣列作為指數,進行運算呢?
二是如何得到求模之後的結果?按道理,起碼應該先把冪運算結果算出來,然後做 % 1337 這個運算。但問題是,指數運算你懂得,真實結果肯定會大得嚇人,也就是說,算出來真實結果也沒辦法表示,早都溢位報錯了。
三是如何高效進行冪運算,進行冪運算也是有演算法技巧的,如果你不了解這個演算法,後文會講解。
那麼對於這幾個問題,我們分開思考,逐個擊破。
如何處理陣列指數
首先明確問題:現在 b 是乙個陣列,不能表示成整型,而且陣列的特點是隨機訪問,刪除最後乙個元素比較高效。
不考慮求模的要求,以 b = [1,5,6,4] 來舉例,結合指數運算的法則,我們可以發現這樣的乙個規律:=
a[1,5,6,4]a4
×a[1,5,6,0]a4
×(a[1,5,6])10
看到這,我們的老讀者肯定已經敏感地意識到了,這就是遞迴的標誌呀!因為問題的規模縮小了:
superpow(a, [1,5,6,4])
=> superpow(a, [1,5,6])
那麼,發現了這個規律,我們可以先簡單翻譯出**框架:
// 計算 a 的 k 次方的結果
// 後文我們會手動實現
int mypow(int a, int k);
int superpow(int a, vector& b)
到這裡,應該都不難理解吧!我們已經解決了 b 是乙個陣列的問題,現在來看看如何處理 mod,避免結果太大而導致的整型溢位。
如何處理 mod 運算
首先明確問題:由於計算機的編碼方式,形如 (a * b) % base 這樣的運算,乘法的結果可能導致溢位,我們希望找到一種技巧,能夠化簡這種表示式,避免溢位同時得到結果。
比如在二分查詢中,我們求中點索引時用 (l+r)/2 轉化成 l+(r-l)/2,避免溢位的同時得到正確的結果。
那麼,說乙個關於模運算的技巧吧,畢竟模運算在演算法中比較常見:
(a * b) % k = (a % k)(b % k) % k
證明很簡單,假設:
a = ak +b;b = ck + d
其中 a,b,c,d 是任意常數,那麼:
ab = ack^2 + adk + bck +bd
ab % k = bd % k
又因為:
a % k = b;b % k = d
所以:(a % k)(b % k) % k = bd % k
綜上,就可以得到我們化簡求模的等式了。
換句話說,對乘法的結果求模,等價於先對每個因子都求模,然後對因子相乘的結果再求模。
那麼擴充套件到這道題,求乙個數的冪不就是對這個數連乘麼?所以說只要簡單擴充套件剛才的思路,即可給冪運算求模:
int base = 1337;
// 計算 a 的 k 次方然後與 base 求模的結果
int mypow(int a, int k)
return res;
}int superpow(int a, vector& b)
你看,先對因子 a 求模,然後每次都對乘法結果 res 求模,這樣可以保證 res *= a 這句**執行時兩個因子都是小於 base 的,也就一定不會造成溢位,同時結果也是正確的。
至此,這個問題就已經完全解決了,已經可以通過 leetcode 的判題系統了。
但是有的讀者可能會問,這個求冪的演算法就這麼簡單嗎,直接乙個 for 迴圈累乘就行了?複雜度會不會比較高,有沒有更高效地演算法呢?
有更高效地演算法的,但是單就這道題來說,已經足夠了。
因為你想想,呼叫 mypow 函式傳入的 k 最多有多大?k 不過是 b 陣列中的乙個數,也就是在 0 到 9 之間,所以可以說這裡每次呼叫 mypow 的時間複雜度就是 o(1)。整個演算法的時間複雜度是 o(n),n 為 b 的長度。
但是既然說到冪運算了,不妨順帶說一下如何高效計算冪運算吧。
如何高效求冪
快速求冪的演算法不止乙個,就說乙個我們應該掌握的基本思路吧。利用冪運算的性質,我們可以寫出這樣乙個遞迴式:
a^ = \begin a \times a^, b\ 為奇數 \ (a), b\ 為偶數 \ \endab
= else }
雖然對於題目,這個優化沒有啥特別明顯的效率提公升,但是這個求冪演算法已經公升級了,以後如果別人讓你寫冪演算法,起碼要寫出這個演算法。
python根據方程的y求x 用Python解方程
我們先從簡單的來 例題1 這是北師大版小學六年級上冊課本95頁的一道解方程練習題 大家可以先口算一下,這道題裡面的x的值為200 接下來我們用python來實現,如下,每一句 後面都寫有解釋語 1 import sympy 引入解方程的專業模組sympy 2 x sympy.symbols x 申明...
2024 求X到Y之間的整數和
time limit 3 second memory limit 2 mb 計算x到y之間的整數和 要求用函式實現 注意輸入時x不一定小於y,且x y不一定都是整數。兩行,第一行為x,第二行為y。一行,x與y之間的整數和 8.512.542 題解 這個處理有點麻煩。先獲取兩個數的整數部分 用int ...
求x到y的最少計算次數 (BFS)
時間限制 1秒 空間限制 262144k 給定兩個 100到100的整數x和y,對x只能進行加1,減1,乘2操作,問最少對x進行幾次操作能得到y?例如 a 3,b 11 可以通過3 2 2 1,3次操作得到11 a 5,b 8 可以通過 5 1 2,2次操作得到8 輸入描述 輸入以英文逗號分隔的兩個...