首页 > 编程语言 >算法学习笔记(36)——快速幂

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

时间:2022-12-10 09:47:43浏览次数:68  
标签:log int res LL 36 笔记 算法 逆元 bmod

快速幂

快速幂

用于快速(在 \(O(\log k)\) 的时间复杂度之内)求出 \(a^k \bmod p\) 的结果,\(1 \le a,p,k \le 10^9\),核心是反复平方法

算法思想:

  1. 预处理出这些值: \(a^{2^0} \bmod p,a^{2^1} \bmod p,a^{2^2} \bmod p,\cdots ,a^{2^{\log k}} \bmod p\)(共 \(\log k\) 个)

    \[\begin{aligned} a^{2^0} &= a\\ a^{2^1} &= (a^{2^0})^2\\ a^{2^2} &= (a^{2^1})^2\\ &\cdots\\ a^{2^{\log k}} &= (a^{2^{\log k - 1}})^2 \end{aligned} \]

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

    \[a^k = a^{2^{x_1}} \cdot a^{2^{x_2}} \cdots a^{2^{x_t}} = a^{2^{x_1} + 2^{x_2} + \cdots + 2^{x_t}} \]

    于是将问题转化为将 \(k\) 拆分为 \(2^0, 2^1, \cdots , 2^{\log k}\) 中若干个数的和,将 \(k\) 化为二进制即可。

    \[\begin{aligned} & k = (110110)_2 \\ & k = 2^5 + 2^4 + 2^2 + 2^1 \end{aligned} \]

题目链接:AcWing 875. 快速幂

时间复杂度:\(O(N\log k)\)

#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/b \equiv a * x \pmod m\) 。称 \(x\) 为 \(b\) 的模 \(m\) 乘法逆元,记为 \(b^{-1}\pmod m\) 。
因为 \(a/b \equiv a * b^{-1} \equiv a/b * b * b^{-1} \pmod m\) ,所以 \(b * b^{-1} \equiv 1 \pmod m\) 。
如果 \(m\) 是质数(此时用 \(p\) 代替 \(m\) )并且 \(b<p\) ,根据费马小定理, \(b^{p-1} \equiv 1 \pmod p\) ,即 \(b * b^{p-2} \equiv 1 \pmod p\) 。因此,当模数 \(p\) 为质数时, \(b^{p-2}\) 即位 \(b\) 的乘法逆元
如果只是保证 \(b,m\) 互质,那么乘法逆元可通过求解同余方程 \(b*x \equiv 1 \pmod m\) 得到
如果 \(b\) 和 \(m\) 不互质,即 \(b\) 是 \(m\) 的倍数时,\(b*x \bmod m\) 一定为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;
}

标签:log,int,res,LL,36,笔记,算法,逆元,bmod
From: https://www.cnblogs.com/I-am-Sino/p/16970792.html

相关文章

  • 算法学习笔记(35)——欧拉函数
    欧拉函数欧拉函数用公式求欧拉函数用筛法求欧拉函数欧拉函数:在数论中,对正整数\(N\),欧拉函数\(\varphi(N)\)是小于等于\(N\)的正整数中与\(N\)互质的数的......
  • 算法学习笔记(34)——约数
    约数约数约数的定义算数基本定理的推论正约数集合正约数个数正约数之和一、试除法求约数二、约数个数三、约数之和四、最大公约数欧几里得算法更相减损......
  • 算法学习笔记(33)——质数
    质数质数一、试除法判定质数二、分解质因数三、筛质数3.1朴素筛法3.2埃氏筛法(Eratosthenes筛法)3.3欧拉筛法(线性筛法)一、试除法判定质数质数的定义:若......
  • 算法学习笔记(43)——背包问题
    背包问题背包问题0/1背包问题完全背包多重背包二进制拆分法分组背包背包是线性DP中一类重要而特殊的模型,本文将其作为单独一部分进行总结整理。0/1背......
  • 算法学习笔记(42)——博弈论
    博弈论博弈论NIM博弈台阶-Nim游戏公平组合游戏ICG有向图游戏Mex运算SG函数有向图游戏的和定理集合-Nim游戏拆分-Nim游戏NIM博弈给定\(n\)堆物品,第......
  • 算法学习笔记(41)——容斥原理
    容斥原理设\(S_1,S_2,\cdots,S_n\)为有限集合,\(|S|\)表示集合\(S\)的大小,则:\[\vert\bigcup\limits_{i=1}^{n}S_i\vert=\sum\limits_{i=1}^{n}\vertS_i\vert......
  • 算法学习笔记(40)——组合计数
    组合计数组合计数求组合数I——预处理组合数求组合数II——预处理阶乘求组合数III——卢卡斯定理(Lucas)求组合数IV——高精度满足条件的01序列——卡......
  • 算法学习笔记(39)——高斯消元
    高斯消元高斯消元高斯消元解线性方程组高斯消元解异或线性方程组高斯消元解线性方程组通过初等行变换把增广矩阵化为阶梯型矩阵,并回代得到方程的解适用于求解......
  • 【Tensorflow深度学习】优化算法、损失计算、模型评估、向量嵌入、神经网络等模块的讲
    OverridetheentrypointofanimageIntroducedinGitLabandGitLabRunner9.4.Readmoreaboutthe extendedconfigurationoptions.Beforeexplainingtheav......
  • 前端入门学习笔记四十七
    OverridetheentrypointofanimageIntroducedinGitLabandGitLabRunner9.4.Readmoreaboutthe extendedconfigurationoptions.Beforeexplainingtheav......