2 solutions
-
2
快速幂 题解
一、问题
计算 a^b mod m。b 最大到 10^9。 如果直接循环 b 次:
for i in range(b): result = result * a % m,10^9 次循环直接 TLE二、核心原理:二分
幂运算有个性质:
← 算一次 ,再平方一次就行 ← 奇数的话拆一个 出来
每一步把指数对半砍, 只要砍约 30 次就到 1 了
三、算法:快速幂
把指数 b 写成二进制。例如 b = 10:
10 的二进制
所以 ^ × 只需要两个关键值: 和
四、 和 怎么得出来?
初始:
看第 位(最低位): 看第 位: ← 平方 看第 位: ← 再平方 看第 位: ← 再平方
b的二进制哪位是 1,就把当前 a 乘进答案
五、手算验证:^
b=10,二进制 1010,从低到高看:
步骤 B B最低位 A(当前值) RESULT 解释 初始 10 - 1 1 10最低位 0,不乘,a 平方 2 5最低位 1,乘入,a 平方 3 2最低位 0,不乘,a 平方 4 1- 最低位 1,乘入 最后 result = 1024,mod 1000 = 24
六、代码
a, b, m = map(int, input().split()) result = 1 a = a % m while b > 0: if b % 2 == 1: # b 的二进制最低位是 1 result = (result * a) % m a = (a * a) % m # a 平方,准备看下一位 b //= 2 # b 右移,砍掉最低位 print(result)using System; class Program { static void Main() { string[] input = Console.ReadLine().Split(); long a = long.Parse(input[0]); long b = long.Parse(input[1]); long m = long.Parse(input[2]); long result = 1; a = a % m; while (b > 0) { if (b % 2 == 1) // 二进制最低位是 1 result = (result * a) % m; a = (a * a) % m; // a 平方 b /= 2; // b 右移 } Console.WriteLine(result); } } -
1
快速幂 — 二进制拆分加速
问题
计算 ,其中 最高可达 。如果直接循环 次, 的时间复杂度必然 TLE。
怎么想?
把 写成二进制形式:
$$b = (b_k b_{k-1} \dots b_1 b_0)_2 = b_0 \cdot 2^0 + b_1 \cdot 2^1 + \dots + b_k \cdot 2^k$$于是:
$$a^b = a^{b_0 \cdot 2^0} \times a^{b_1 \cdot 2^1} \times \dots \times a^{b_k \cdot 2^k}$$其中每个 。当 时,乘上对应的 ; 时跳过。
而 可以通过反复平方得到:。
这样只需要 次运算, 时 次,比 次循环快了三千多万倍!
位运算实现
如何判断 的二进制第 位是 还是 ?—— 答案:位运算!
运算 含义 示例 b & 1取 的最低位(第 位) 13 & 1=1b >>= 1右移一位(去掉最低位) 13 >> 1=6算法流程:
b & 1检查当前最低位,若为 则乘入答案a = a * a % m计算下一次的基底(平方)b >>= 1右移一位,继续处理下一个二进制位- 当
b == 0时结束
以 为例:
轮次 (二进制) 的幂次 乘入? 答案 1 11011 ✓ 2 1100 ✗ 3 111 ✓ 4 15 0— ,仅需 轮!
复杂度
- 时间:,每次循环做常数次乘法和位运算
- 空间:
代码
#include <bits/stdc++.h> using namespace std; typedef long long ll; ll fast_pow(ll a, ll b, ll m) { ll res = 1 % m; // 注意 m 可能为 1 a %= m; while (b) { if (b & 1) // 最低位是 1 吗? res = (res * a) % m; a = (a * a) % m; // 平方,准备下一位 b >>= 1; // 右移,处理下一个二进制位 } return res; } int main() { ios::sync_with_stdio(false), cin.tie(NULL); ll a, b, m; cin >> a >> b >> m; cout << fast_pow(a, b, m) << '\n'; return 0; }
- 1
Information
- ID
- 6
- Time
- 1000ms
- Memory
- 256MiB
- Difficulty
- 2
- Tags
- # Submissions
- 15
- Accepted
- 7
- Uploaded By