当前位置: 首页 > article >正文

Acwing 快速幂

1.快速幂

作用:可以快速求出 a k m o d p a^k mod p akmodp的值,时间复杂度是 O ( l o g k ) . O( log k). O(logk).
核心思路:反复平方法
①预处理出: a 2 0 m o d   p 、 a 2 1 m o d   p 、 a 2 2 m o d   p 、 … 、 a 2 log ⁡ 2 k m o d   p 一共 l o g 2 k 个数 对于这预处理出的数,观察可以发现: a 2 1 = ( a 2 0 ) 2 、 a 2 2 = ( a 2 1 ) 2 、 a 2 3 = ( a 2 2 ) 2 、 … 、 a 2 l o g 2 k = ( a 2 l o g 2 k − 1 ) 2 . 即每个数是前面一个数的平方 ②对于 a k ,可将 a k 拆成 a k = a 2 x 1 × a 2 x 2 × ⋯ × a 2 x t = a 2 x 1 + 2 x 2 + ⋯ + 2 x t 可得到 k = 2 x 1 + 2 x 2 + ⋯ + 2 x t  ,即 k 为 l o g 2 k 个数之和 ​那么 a k m o d   p = ( a 2 x 1 m o d   d ) ∗ ( a 2 x 2 m o d   d ) . . . ( a 2 x t m o d   d ) 再由①中得到的每个数是前一个数的平方,故 a k m o d   p = ( a 2 x 1 m o d   d ) ∗ [ ( a 2 x 1 m o d   d ) ] 2 m o d   d   ∗ . . . ∗ ( 前一个结果的平方 m o d   d ) ③对于怎么得到 a k = a 2 x 1 + 2 x 2 + ⋯ + 2 x t ,简单,直接取 k 的二进制数。 如求 4 5 m o d   10 ,则 k = ( 101 ) 2 ,那么 4 5 = 4 ( 101 ) 2 = 4 2 0 × 4 2 2 而 4 2 0 m o d   10 = 4 , 4 2 1 m o d   10 = 4 2 m o d   10 = 6 , 4 2 2 m o d   10 = 6 2 m o d   10 = 6 , ( 这里就体现了后面的结果为前一个结果的平方再取模 ) 得到最终结果即为 4 5 m o d   10 = 4 ∗ 6   m o d   10 = 4 ①预处理出:a^{2^{0}} mod\ p、a^{2^{1}} mod\ p、a^{2^{2}} mod\ p、\dots、a^{2^{\log_{2}{k} }} mod\ p 一共log_{2}{k}个数\\ 对于这预处理出的数,观察可以发现:a^{2^{1}}=(a^{2^{0}})^2、a^{2^{2}}=(a^{2^{1}})^2、a^{2^{3}}=(a^{2^{2}})^2、\dots、a^{2^{log_{2}{k}}}=(a^{2^{log_{2}{k}-1}})^2.\\即每个数是前面一个数的平方\\ ②对于a^{k},可将 a^{k} 拆成 a^{k} = a^{2^{x_{1}}} \times a^{2^{x_{2}}} \times \dots \times a^{2^{x_{t}}} = a^{2^{x_{1}}+2^{x_{2}}+\dots+2^{x_{t}}}\\可得到k=2^{x_{1}}+2^{x_{2}}+\dots+2^{x_{t}}\ ,即k为log_{2}{k}个数之和\\​那么a^{k} mod\ p=(a^{2^{x_{1}}}mod \ d)*(a^{2^{x_{2}}}mod \ d)...(a^{2^{x_{t}}}mod \ d)\\再由①中得到的每个数是前一个数的平方,故a^{k} mod\ p=(a^{2^{x_{1}}}mod \ d)*[(a^{2^{x_{1}}}mod \ d)]^2 mod\ d\ * ...*\\(前一个结果的平方mod\ d)\\\\③对于怎么得到a^{k}=a^{2^{x_{1}}+2^{x_{2}}+\dots+2^{x_{t}}},简单,直接取k的二进制数。\\ \\如求4^5 mod \ 10,则k=(101)_2,那么4^{5}=4^{(101)_{2}}=4^{2^{0}}\times 4^{2^{2}}\\而4^{2^{0}} mod\ 10=4,4^{2^{1}}mod\ 10=4^2 mod \ 10=6,4^{2^{2}}mod\ 10=6^2 mod \ 10=6,\\(这里就体现了后面的结果为前一个结果的平方再取模)\\得到最终结果即为4^5 mod \ 10=4*6 \ mod \ 10=4 预处理出:a20mod pa21mod pa22mod pa2log2kmod p一共log2k个数对于这预处理出的数,观察可以发现:a21=(a20)2a22=(a21)2a23=(a22)2a2log2k=(a2log2k1)2.即每个数是前面一个数的平方对于ak,可将ak拆成ak=a2x1×a2x2××a2xt=a2x1+2x2++2xt可得到k=2x1+2x2++2xt ,即klog2k个数之和那么akmod p=(a2x1mod d)(a2x2mod d)...(a2xtmod d)再由中得到的每个数是前一个数的平方,故akmod p=(a2x1mod d)[(a2x1mod d)]2mod d ...(前一个结果的平方mod d)对于怎么得到ak=a2x1+2x2++2xt,简单,直接取k的二进制数。如求45mod 10,则k=(101)2,那么45=4(101)2=420×422420mod 10=4421mod 10=42mod 10=6422mod 10=62mod 10=6(这里就体现了后面的结果为前一个结果的平方再取模)得到最终结果即为45mod 10=46 mod 10=4

Acwing 875.快速幂

在这里插入图片描述
具体实现代码(详解版):

#include <iostream> 
using namespace std; 

typedef long long LL; 

// 快速幂函数:计算 m^k % p
LL qmi(int m, int k, int p) {
    // res 初始化为 1 % p,确保即使 p == 1 也能正常工作(防止 p = 1 时除 0 错误)
    int res = 1 % p; 
    int t = m; // t 是当前的底数,从 m 开始

    // 当 k 不为 0 时,继续循环
    while (k) {
        // 如果 k 的最低位是 1,意味着当前需要将 t 乘到结果中
        if (k & 1) 
            res = (LL)res * t % p; // 计算 (res * t) % p,并更新 res

        // 无论 k 的最低位是否为 1,都要将 t 平方,并取模 p
        t = (LL)t * t % p;

        // 右移 k,去掉最低位,这相当于将 k 除以 2
        k >>= 1;
    }

    // 返回最终的结果,即 m^k % p
    return res;
}

int main() {
    int n; 
    cin >> n; 
    
    while (n--) {
        int m, k, p;
        cin >> m >> k >> p; 
        cout << qmi(m, k, p) << endl; // 输出 m^k % p 的结果
    }

    return 0;
}

2.快速幂求逆元

Acwing 快速幂求逆元

在这里插入图片描述
实现思路:

  • 由(a/b)mod m恒等a*x mod m===>(b*x) mod m = 1 ,x为b的逆元
  • 结合费马定理(欧拉函数的应用):b与m互质,且m为质数,则b^(m-1) mod m=1;
  • 上面两式结合:得b的逆元b^(m-2),则模m乘法逆元x=b^(m-2)%m本质上就是求快速幂,但多了一个要求:b和m互质
  • 注意:当b和m不互质时,无解;否则必存在逆元

具体实现代码(详解版):

#include <iostream> 
using namespace std; 

typedef long long LL; // 定义 LL 为 long long 类型,用于处理大整数

// 快速幂函数:计算 m^k % p
LL qmi(int m, int k, int p) {
    // res 初始化为 1 % p,确保即使 p == 1 也能正常工作(防止 p = 1 时除 0 错误)
    int res = 1 % p; 
    int t = m; // t 是当前的底数,从 m 开始
    
    // 当 k 不为 0 时,继续循环
    while (k) {
        // 如果 k 的最低位是 1,意味着当前需要将 t 乘到结果中
        if (k & 1) 
            res = (LL)res * t % p; // 计算 (res * t) % p,并更新 res
        
        // 无论 k 的最低位是否为 1,都要将 t 平方,并取模 p
        t = (LL)t * t % p;
        
        // 右移 k,去掉最低位,这相当于将 k 除以 2
        k >>= 1;
    }
    
    // 返回最终的结果,即 m^k % p
    return res;
}

int main() {
    int n; 
    cin >> n; 
    
   
    while (n--) {
        int m, p;
        cin >> m >> p; // 读取基数 m 和模数 p
        
        // 根据费马小定理计算 m 的模逆元,公式为 m^(p-2) mod p
        int res = qmi(m, p - 2, p);
        
        // 检查 m 是否与 p 互质(即 m % p 不为 0)
        if (m % p) 
            cout << res << endl; // 如果互质,输出结果
        else 
            puts("impossible"); // 如果不互质,输出 "impossible"
    }
    
    return 0; 
}

快速幂的应用:
在这里插入图片描述


http://www.kler.cn/news/324795.html

相关文章:

  • 力扣 简单 876.链表的中间结点
  • Leetcode面试经典150题-383.赎金信
  • 2024年【电工(高级)】考试题及电工(高级)考试内容
  • ISO 21434车辆网络安全风险评估的全面流程解析
  • 小柴冲刺软考中级嵌入式系统设计师系列二、嵌入式系统硬件基础知识(3)嵌入式系统的存储体系
  • 大模型落地需要一把“梯子”
  • 酒店智能开关的组成与功能
  • 【第十四周】PyTorch深度学习实践1
  • 浅说差分算法(上)
  • excel-VBA知识点记录
  • 服务器数据恢复—SAN环境下LUN映射出错导致文件系统一致性出错的数据恢复案例
  • 物联网系统中OLED屏主流驱动方案详解
  • 每日OJ题_牛客_HJ108求最小公倍数_C++_Java
  • unixODBC编程(四)插入数据
  • 【js】Node.js的fs的使用方法
  • 长沙某公司.Net高级开发面试题
  • 【C语言零基础入门篇 - 15】:单链表
  • 甄选范文“论应用服务器基础软件”,软考高级论文,系统架构设计师论文
  • 静态路由和默认路由(实验)
  • 海滨体育馆管理系统:SpringBoot实现技巧与案例
  • 活动在线报名小程序源码系统 自主提交表单+创建表单 带完整的安装代码包以及搭建部署教程
  • LiveGBS流媒体平台GB/T28181功能-支持电子放大拉框放大直播视频拉框放大录像视频流拉框放大电子放大
  • 小阿轩yx-Ansible部署与应用基础
  • linux semaphore信号量操作
  • 基于nodejs+vue的农产品销售管理系统
  • 如何制作小程序商城
  • NLP任务的详细原理与步骤的详细讲解
  • 算法 求最大葫芦数
  • 如何选择合适的跨境网络专线?
  • 加速 Python for 循环