题解:AcWing 875 快速幂
【题目来源】
AcWing:875 快速幂 - AcWing题库
【题目描述】
给定 \(n\) 组 \(a_i,b_i,p_i\),对于每组数据,求出 \(a_i^{b_i} \ mod \ p_i\) 的值。
【输入】
第一行包含整数 \(n\)。
接下来 \(n\) 行,每行包含三个整数 \(a_i,b_i,p_i\)。
【输出】
对于每组数据,输出一个结果,表示 \(a_i^{b_i} \ mod \ p_i\) 的值。
每个结果占一行。
【输入样例】
2
3 2 5
4 3 9
【输出样例】
4
1
【核心思想】
-
问题分析:给定 \(n\) 组 \((a_i, b_i, p_i)\),求 \(a_i^{b_i} \bmod p_i\) 的值。若直接进行 \(b_i\) 次乘法,时间复杂度为 \(O(b_i)\),在指数极大时不可行。这是一个经典的数学问题,核心在于利用快速幂算法(二进制幂)将时间复杂度降至 \(O(\log b_i)\)。
-
算法选择:
- 二进制快速幂:将指数 \(b\) 分解为二进制形式 \(b = b_0 \cdot 2^0 + b_1 \cdot 2^1 + b_2 \cdot 2^2 + \cdots\),则 \(a^b = a^{b_0 \cdot 2^0} \cdot a^{b_1 \cdot 2^1} \cdot a^{b_2 \cdot 2^2} \cdots\)
- 模运算优化:每次乘法和平方后立即取模,防止数值溢出并满足题目要求
- 迭代实现:使用循环而非递归,避免栈溢出风险,代码更简洁高效
-
关键步骤:
- 读取输入:整数 \(n\)(查询次数),以及 \(n\) 组 \((a, b, p)\)
- 快速幂函数
qmi(a, k, p):- 初始化
res = 1(任何数的 \(0\) 次幂为 \(1\)) - 当 \(k > 0\) 时循环:
- 若 \(k\) 的最低位为 \(1\)(
k & 1):res = res * a % p,将当前幂次乘入结果 a = a * a % p:将底数平方,对应下一位的幂次(\(a^1 \to a^2 \to a^4 \to a^8 \cdots\))k >>= 1:右移一位,处理下一个二进制位
- 若 \(k\) 的最低位为 \(1\)(
- 返回
res
- 初始化
- 处理每组数据:调用
qmi(a, b, p)并输出结果
-
时间/空间复杂度:
- 时间复杂度:\(O(n \cdot \log b_i)\)。单次快速幂的循环次数等于指数 \(b_i\) 的二进制位数,即 \(O(\log b_i)\)
- 空间复杂度:\(O(1)\),仅使用常数额外变量
-
快速幂的核心思想:
- 二进制分解:任何正整数都可以唯一表示为若干 \(2\) 的幂次之和。利用这一点,将 \(a^b\) 转化为若干预计算好的 \(a^{2^k}\) 的乘积
- 平方递推:通过不断对底数平方(\(a \to a^2 \to a^4 \to a^8\)),在 \(O(\log b)\) 步内预计算出所有可能需要的高次幂
- 按位累乘:根据指数二进制表示中每一位是否为 \(1\),决定是否将对应的高次幂乘入结果
- 模运算结合:在乘法过程中立即取模,利用 \((x \cdot y) \bmod p = ((x \bmod p) \cdot (y \bmod p)) \bmod p\) 的性质,确保中间结果不会溢出
- 适用于大指数模运算、矩阵快速幂、快速幂求逆元等场景
【算法标签】
快速幂
【代码详解】
#include <bits/stdc++.h>
using namespace std;
typedef long long LL; // 定义长整型别名,防止乘法溢出
// 快速幂算法:计算 a^k mod p
int qmi(int a, int k, int p)
{
int res = 1; // 初始化结果为1(a^0 = 1)
// 当指数k不为0时循环
while (k)
{
// 如果当前最低位为1,将a乘入结果
if (k & 1)
res = (LL)res * a % p; // 强制转换为LL防止溢出
// a平方,准备处理下一位
a = (LL)a * a % p; // 强制转换为LL防止溢出
// 右移一位,处理下一个二进制位
k >>= 1;
}
return res;
}
int main()
{
int n; // 查询次数
scanf("%d", &n);
// 处理每个查询
while (n--)
{
int a, k, p; // 底数、指数、模数
scanf("%d%d%d", &a, &k, &p);
// 调用快速幂函数并输出结果
printf("%d\n", qmi(a, k, p));
}
return 0;
}
【运行结果】
2
3 2 5
4
4 3 9
1
浙公网安备 33010602011771号