题目链接
题目描述
给定 组数据,每组数据包含三个正整数
。求
的值。
输入描述:
第一行一个整数 ,表示数据组数。
接下来
行,每行三个正整数
。
输出描述:
对于每组数据,输出一行,表示 的结果。
解题思路
本题要求计算 。当指数
非常大时,直接使用循环乘以
次的方法(时间复杂度为
)会超时。因此,我们需要使用 快速幂算法,也叫作 二进制取幂 (Binary Exponentiation),将时间复杂度优化到
。
快速幂原理
该算法的核心思想是利用指数 的二进制表示。
任何一个正整数
都可以被表示为其二进制形式,例如:
其中
是
的二进制位。
那么, 可以写成:
观察这个式子,每一项都是 的形式。我们可以很方便地通过自乘来递推得到这些项:
。
...
因此,我们只需要遍历 的二进制位。如果第
位是 1(即
),我们就将最终结果乘上
。
算法步骤 (迭代实现):
- 初始化结果
res = 1 % m
。将结果初始化为1 % m
而不是简单的1
是一个关键细节。它能正确处理模数为1
的边界情况:当m=1
,1 % 1
为0
,符合任何数模1
都为0
的规则;当m>1
,1 % m
依然为1
,不影响常规计算。 - 将底数
对
取模,即
a = a % m
。这可以防止中间计算溢出,并利用模运算性质。
- 当
时,进入循环: a. 判断
的最低位:如果
是奇数 (即
b & 1 == 1
),说明的二进制表示中当前最低位为 1,此时需要将
res
乘上当前的a
。即res = (res * a) % m
。 b. 更新底数:将a
平方,即a = (a * a) % m
。这对应于从计算
。 c. 更新指数:将
右移一位(即
b >>= 1
或b = b / 2
),以检查下一位。 - 循环结束后,
res
就是的结果。
代码
#include <iostream>
using namespace std;
long long power(long long base, long long exp, long long mod) {
long long res = 1 % mod;
base %= mod;
while (exp > 0) {
if (exp % 2 == 1) res = (res * base) % mod;
base = (base * base) % mod;
exp /= 2;
}
return res;
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL);
int T;
cin >> T;
while (T--) {
long long a, b, m;
cin >> a >> b >> m;
cout << power(a, b, m) << endl;
}
return 0;
}
import java.util.Scanner;
public class Main {
public static long power(long base, long exp, long mod) {
long res = 1 % mod;
base %= mod;
while (exp > 0) {
if (exp % 2 == 1) {
res = (res * base) % mod;
}
base = (base * base) % mod;
exp /= 2;
}
return res;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int T = sc.nextInt();
while (T-- > 0) {
long a = sc.nextLong();
long b = sc.nextLong();
long m = sc.nextLong();
System.out.println(power(a, b, m));
}
}
}
# Python 的内置函数 pow(base, exp, mod) 是执行模幂运算最地道、
# 最高效的方式。它能正确处理 m=1 的边界情况,返回 0。
T = int(input())
for _ in range(T):
a, b, m = map(int, input().split())
print(pow(a, b, m))
算法及复杂度
- 算法:快速幂 / 二进制取幂
- 时间复杂度:
,对于每个测试用例,快速幂算法需要对指数
进行对数次操作。
- 空间复杂度:
,迭代实现只需要常数空间。