2 solutions
-
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; }
Information
- ID
- 6
- Time
- 1000ms
- Memory
- 256MiB
- Difficulty
- 2
- Tags
- # Submissions
- 15
- Accepted
- 7
- Uploaded By