算法学习笔记(36)——快速幂
快速幂
快速幂
用于快速(在 的时间复杂度之内)求出 的结果,,核心是反复平方法。
算法思想:
- 预处理出这些值: (共 个)
- 若要求得 ,则我们首先将 拆分为预处理出的若干个值的乘积的形式,即:于是将问题转化为将 拆分为 中若干个数的和,将 化为二进制即可。
时间复杂度:
#include <iostream>
using namespace std;
typedef long long LL;
LL quick_mi(int a, int k, int p)
{
LL res = 1;
// k=0时跳出循环
while (k) {
// 如果k的个位是1,则将对应的预处理值算入乘积(a是动态变化的)
if (k & 1) res = (LL)res * a % p;
// 当前个位处理结束,右移一位
k >>= 1;
// 更新a的值
a = (LL)a * a % p;
}
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", quick_mi(a, k, p));
}
return 0;
}
快速幂求逆元
乘法逆元
若整数 互质,并且 ,则存在一个整数 ,使得 。称 为 的模 乘法逆元,记为 。
因为 ,所以 。
如果 是质数(此时用 代替 )并且 ,根据费马小定理, ,即 。因此,当模数 为质数时, 即位 的乘法逆元。
如果只是保证 互质,那么乘法逆元可通过求解同余方程 得到。
如果 和 不互质,即 是 的倍数时, 一定为0,所以一定无解
#include <iostream>
using namespace std;
typedef long long LL;
// 快速幂,返回 a^k % p
LL quick_mi(int a, int k, int p)
{
LL res = 1;
while (k) {
if (k & 1) res = (LL)res * a % p;
k >>= 1;
a = (LL)a * a % p;
}
return res;
}
int main()
{
int n;
scanf("%d", &n);
while (n -- ) {
int a, p;
scanf("%d%d", &a, &p);
// 当a时p的倍数时,a * x mod p一定为0,不可能等于1,所以无解
if (a % p == 0) puts("impossible");
// 当模数 p 为质数时,a^{p−2} 即为 a 的乘法逆元
else printf("%d\n", quick_mi(a, p - 2, p));
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】