快速幂+快速幂取模
快速冪是優化的冪運算算法。
快速冪取模是快速冪+同余定理。
一、暴力冪運算
考慮計算 311,可以讓3累乘11次,復雜度是O(n)
int Pow1(int a, int b) {int ans = 1;for (int i = 0; i < b; i++) ans *= a;return ans; }int main() {cout << Pow1(3, 11) << endl;return 0; }輸出:
177147二、快速冪
以 311 舉例。把指數11寫成二進制形式是1011,所以
11 = 23 + 0 × 22 + 21 + 20
所以 311 又可以寫成:
311 =3^ (23 + (0 × 22) + 21 + 20)
拆括號得:
311 = 38 × (0 × 34) × 32 × 31
可以發現乘法因子是以平方的形式增長的,比如 32 等于 31 的平方,38 等于 34 的平方。
由此規律,可以寫出快速冪算法了。
我們先定義一個ans=1來保存答案,然后從低到高遍歷指數b的每一個二進制位,同時我們讓底數a隨著循環每次做一個平方,a, a2, a4, a8,…。
可以寫出快速冪的框架:
因為11是1011,311 = 38 × (0 × 34) × 32 × 31,可以發現,當二進制位等于1時,ans要累乘一次a。因此完整代碼如下:
#include <iostream> using namespace std;int Pow(int a, int b) {int ans = 1;while (b) {//因為1的二進制是0000 0001,所以 b & 1 為真就意味著 b 的最低位是1。if (b & 1) ans *= a;a *= a;b >>= 1;}return ans; }int main() {cout << Pow(3, 11) << endl;return 0; }以上就是快速冪算法的分析。
三、快速冪取模
快速冪取模可以用來解決 “1145141919810 除以6的余數等于多少”或者是“230的后6位是多少”之類的問題。它是在快速冪的基礎上,結合了同余定理。
#include <iostream> using namespace std;int Pow(int a, int b, int c) {int ans = 1;while (b) {if (b & 1) ans = ans * a % c;a = a * a % c;b >>= 1;}return ans; }int main() {cout << Pow(114514, 1919810, 6) << endl;cout << Pow(2, 30, 1000000) << endl;return 0; }輸出:
4 741824總結
- 上一篇: 【贪心】P1056 排座椅
- 下一篇: 【STL】string的增删改查