算法学习笔记(36)——快速幂

快速幂

快速幂

用于快速(在 O(logk) 的时间复杂度之内)求出 akmodp 的结果,1a,p,k109,核心是反复平方法

算法思想:

  1. 预处理出这些值: a20modp,a21modp,a22modp,,a2logkmodp(共 logk 个)

    a20=aa21=(a20)2a22=(a21)2a2logk=(a2logk1)2

  2. 若要求得 ak,则我们首先将 ak 拆分为预处理出的若干个值的乘积的形式,即:

    ak=a2x1a2x2a2xt=a2x1+2x2++2xt

    于是将问题转化为将 k 拆分为 20,21,,2logk 中若干个数的和,将 k 化为二进制即可。

    k=(110110)2k=25+24+22+21

题目链接:AcWing 875. 快速幂

时间复杂度:O(Nlogk)

#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;
}

快速幂求逆元

乘法逆元
若整数 b,m 互质,并且 b|a ,则存在一个整数 x ,使得 a/bax(modm) 。称 xb 的模 m 乘法逆元,记为 b1(modm)
因为 a/bab1a/bbb1(modm) ,所以 bb11(modm)
如果 m 是质数(此时用 p 代替 m )并且 b<p ,根据费马小定理, bp11(modp) ,即 bbp21(modp) 。因此,当模数 p 为质数时, bp2 即位 b 的乘法逆元
如果只是保证 b,m 互质,那么乘法逆元可通过求解同余方程 bx1(modm) 得到
如果 bm 不互质,即 bm 的倍数时,bxmodm 一定为0,所以一定无解

题目链接:AcWing 876. 快速幂求逆元

#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;
}
posted @   S!no  阅读(27)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示