求x y z,其中y超出long long長度

2021-10-25 02:08:03 字數 2466 閱讀 4218

今天來聊一道與數**算有關的題目,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 輸入描述 輸入以英文逗號分隔的兩個...