数据结构与算法学习笔记----快速幂

news2025/1/6 17:21:49

数据结构与算法学习笔记----快速幂

@@ author: 明月清了个风
@@ first publish time: 2025.1.2

ps⭐️快速幂的两道模版题,快速幂,乘法逆元,费马小定理

Acwing 875. 快速幂

[原题链接](875. 快速幂 - AcWing题库)

给定 n n n a i , b i , p i a_i,b_i,p_i ai,bi,pi,对于每组数据,求出 a i b i    m o d    p i a_i^{b_i} \; mod \; p_i aibimodpi的值

输入格式

第一行包含整数 n n n

接下来 n n n行,每行包含三个整数 a i , b i , p i a_i,b_i,p_i ai,bi,pi

输出格式

对于每组数据,输出一个结果,表示 a i b i    m o d    p i a_i^{b_i} \; mod \; p_i aibimodpi的值。

每个结果占一行。

数据范围

1 ≤ n ≤ 100000 1 \le n \le 100000 1n100000,

1 ≤ a i , b i , p i ≤ 2 × 1 0 9 1 \le a_i,b_i,p_i \le 2\times 10^9 1ai,bi,pi2×109

思路

快速幂是一种高效的计算整数幂的算法,适用于大数的幂运算,比如这题的数据范围, a i , b i , p i a_i,b_i,p_i ai,bi,pi都可以到亿的级别,通过快速幂可以将暴力运算的 O ( n ) O(n) O(n)时间复杂度优化到 O ( log ⁡ n ) O(\log n) O(logn)级别, n n n是幂的范围。

核心思想:将指数 b b b通过二进制分解,从而达到 log ⁡ b \log b logb的运算量,也就是

a b    m o d    p = a ( 2 x 1 ) + 2 x 2 + ⋯ + 2 x k    m o d    p = a 2 x 1 a 2 x 2 ⋯ a 2 x k    m o d    p = ( a 2 x 1 m o d    p ) ⋅ ( a 2 x 2 m o d    p ) ⋯ ( a 2 x k m o d    p ) \begin{align*} a^b \; mod \; p & = a^{(2^{x_1}) + 2^{x_2} + \cdots + 2^{x_k}} \; mod \; p \\ & = a^{2 ^ {x_1}} a^{2 ^ {x_2}} \cdots a^{2^{x_k}} \; mod \; p \\ & = (a^{2^{x_1}}mod \;p)\cdot(a^{2^{x_2}}mod \;p) \cdots(a^{2^{x_k}}mod \;p) \\ \end{align*} abmodp=a(2x1)+2x2++2xkmodp=a2x1a2x2a2xkmodp=(a2x1modp)(a2x2modp)(a2xkmodp)

在代码中,我们也无需对 k k k的二进制分解及 a x a^x ax进行预处理,只需要边运算边处理就行,具体看下面代码吧,代码还是很清晰的。

代码

#include <iostream>
#include <cstring>

using namespace std;

typedef long long LL;

int qmi(int a, int k, int p)
{
   int res = 1;
   
   while(k)   
   {
       if(k & 1) res = (LL) res * a % p;   // 从k的二进制表示最低位开始,也就是2的0次方,此时a的2的0次方就是a
       k >>= 1;  // 每次右移一位
       a = (LL) a * a % p;  // 每次将a平方,因为a上面是2的次方,每次提高一位相当于乘一个a的2的0次方,就是a
   }
   return res;
}

int main()
{
    int n;
    cin >> n;
    
    while(n --)
    {
        int a, b, p;
        cin >> a >> b >> p;
        cout << qmi(a, b, p) << endl;
    }
    
    return 0;
}

Acwing 876. 快速幂求逆元

[原题链接](876. 快速幂求逆元 - AcWing题库)

给定 n n n a i , p i a_i,p_i ai,pi,其中 p i p_i pi是质数,求 a i a_i ai p i p_i pi的乘法逆元,若逆元不存在则输出impossible

注意:请返回 0 ∼ p − 1 0 \sim p - 1 0p1之间的逆元。

乘法逆元的定义

若整数 b , m b,m bm互质,并且对于任意的整数 a a a,如果满足 b ∣ a b|a ba,则存在一个整数 x x x,使得 a b ≡ a × x ( m o d    m ) \frac{a}{b} \equiv a \times x (mod \; m) baa×x(modm),则称 x x x b b b m m m的乘法逆元,记为 b − 1 ( m o d    m ) b^{-1}(mod \; m) b1(modm)

b b b存在乘法逆元的充要条件是 b b b与模数 m m m互质,当模数 m m m为质数时, b m − 2 b^{m - 2} bm2即为 b b b的乘法逆元。

输入格式

第一行包含整数 n n n

接下来 n n n行,每行包含一个数组 a i , p i a_i,p_i ai,pi,数据保证 p i p_i pi是质数。

输出格式

输出共 n n n行,每组数据输出一个结果,每个结果占一行。

a i a_i ai p i p_i pi的乘法逆元存在,则输出一个整数表示逆元,否则输出impossbile

数据范围

1 ≤ n ≤ 1 0 5 1 \le n \le 10^5 1n105

1 ≤ a i , p i ≤ 2 ∗ 1 0 9 1 \le a_i, p_i \le 2 * 10^9 1ai,pi2109

思路

主要的难点是定义比较绕,我们可以对定义的式子进行一些变形

a b ≡ a × x ( m o d    m ) (1) \frac{a}{b} \equiv a \times x (mod \; m) \tag{1} baa×x(modm)(1)

在式(1)的两边同乘 b b b,我们可以得到式(2)

a ≡ b × a × x ( m o d    m ) (2) a \equiv b \times a \times x (mod \; m) \tag{2} ab×a×x(modm)(2)

两边再同时除 a a a可以得到

1 ≡ b × x ( m o d    m ) (3) 1 \equiv b \times x (mod \; m) \tag{3} 1b×x(modm)(3)

因此我们要求的就是一个 x x x,可以使 b × x ≡ 1 ( m o d    m ) b \times x \equiv 1 (mod \; m) b×x1(modm)

还有一个注意点是 b b b存在乘法逆元的充要条件是模数 m m m b b b互质,题目中给出了条件模数 p i p_i pi保证了是质数,也就是保证了这个条件。

这里需要补充一个额外的定理:费马小定理

m m m是一个质数,对于任意整数 a a a a a a不被 m m m整除),有 a m − 1 ≡ 1 ( m o d    m ) a^{m- 1} \equiv 1 (mod \; m) am11(modm)

那么对费马小定理的这个公式进行变形,拆分次方可得 a ⋅ a m − 2 ≡ 1    ( m o d    m ) a \cdot a^{m - 2} \equiv 1 \; (mod \; m) aam21(modm),我们就能直接得到 a a a的乘法逆元是 a m − 2 a^{m - 2} am2

因此问题转换为求 a m − 2 a^{m - 2} am2,也就是应用上面的快速幂。

需要注意的是题目虽然保证了 p p p是一个质数,但是却被没有保证我们的充要条件,也就是 a i a_i ai p i p_i pi互质,因此需要判断 a i a_i ai是否是 p i p_i pi的倍数,只有这样的情况他们才不互质。

代码

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>

using namespace std;

typedef long long LL;

int qmi(int a, int k, int p)
{
    int 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;
    cin >> n;
    
    while(n --)
    {
        int a, p;
        cin >> a >> p;
        if(a % p == 0) puts("impossible");
        else cout << qmi(a, p - 2, p) << endl;
    }
    
    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2271004.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

leecode300.最长递增子序列

dp[i]表示以nums[i]这个数结尾的时的严格递增子序列的最长长度&#xff0c;那么只要每次增加一个数字nums[i]并且这个nums[i]比之前的nums[j]要大&#xff0c;dp[i]就要更新为dp[i]和dp[j]1二者的最大值&#xff0c;初始化默认最大递增子序列都是1 这里遍历顺序的感觉很像多重…

termux配置nginx+php

只能以默认用户u0_axx运行,修改用户会报错An error occurred.或者file no found 安装nginx pkg install nginx安装php-fpm pkg install nginx修改nginx配置文件, nano ../usr/etc/nginx/nginx.conf#端口必须设置在1024以上(1024以下需要root,但php-fpm不能以root用户运行,n…

typescript安装后仍然不能使用tsc,如何解决

1.全局安装 npm i typescript -g 2.发现仍然不行 解决方法&#xff1a; C:\Users\你的用户名\AppData\Roaming\npm解决办法&#xff1a; 1.确定对应的文件下载了 我们发现typescript是下载了的 2.设置环境变量的path 路径为typescript下的npm 3.cmd运行

SQL字符串截取函数——Left()、Right()、Substring()用法详解

SQL字符串截取函数——Left&#xff08;&#xff09;、Right&#xff08;&#xff09;、Substring&#xff08;&#xff09;用法详解 1. LEFT() 函数&#xff1a;从字符串的左侧提取指定长度的子字符串。 LEFT(string, length)string&#xff1a;要操作的字符串。length&#x…

数字PWM直流调速系统设计(论文+源码)

2.1 系统方案设计 2.2.1开环控制方案 采用开环方案的系统架构如图2.1所示&#xff0c;这种方式不需要对直流电机的转速进行检测&#xff0c;在速度控制时单片机只需要直接发出PWM就可以实现直流电机速度的控制。这种方式整体设计难度较低&#xff0c;但是无法准确得知当前的…

Python | 学习type()方法动态创建类

getattr方法的使用场景是在访问不存在的属性时&#xff0c;会触发该方法中的处理逻辑。尤其是在动态属性获取中结合 type()动态创建类有着良好的使用关系。 type()方法常用来判断属性的类别&#xff0c;而动态创建类不常使用&#xff0c;通过如下的几个实例来学习使用&#xff…

CDP集群安全指南-静态数据加密

[一]静态数据加密的架构 CDP 支持两种加密组件&#xff0c;这些组件可以组合成独特的解决方案。在选择密钥管理系统&#xff08;KMS&#xff09;时&#xff0c;您需要决定哪些组件能够满足企业的密钥管理和加密需求。 CDP 加密组件 以下是 Cloudera 用于静态数据加密的组件描…

无线AP安装注意事项

现在的办公楼、酒店等项目中都设计含有网络无线覆盖这一项&#xff0c;在项目实施中&#xff0c;往往采用的是便捷并且后期便于网络无线设备管理的无线ap设备&#xff0c;作为前端无线信号的覆盖。在具体安装无线AP过程中&#xff0c;我们必须要注意以下几点才能保证项目实施完…

【动手学电机驱动】STM32-MBD(2)将 Simulink 模型部署到 STM32G431 开发板

STM32-MBD&#xff08;1&#xff09;安装 STM32 硬件支持包 STM32-MBD&#xff08;2&#xff09;Simulink 模型部署 【动手学电机驱动】STM32-MBD&#xff08;2&#xff09;Simulink 模型部署 1. 软硬件条件和环境测试1.1 软硬件条件1.2 开发环境测试 2. 创建基于 STM32 处理器…

adb 不是内部或外部命令,也不是可运行的程序或批处理文件。

1、问题概述&#xff1f; 本文讲述的是在window系统中安装了Android SDK之后&#xff0c;adb无法使用的情况。 在cmd中执行adb devices提示如下问题&#xff1a; adb 不是内部或外部命令&#xff0c;也不是可运行的程序或批处理文件。 问题&#xff1a;没有配置android sdk环…

Win11+WLS Ubuntu 鸿蒙开发环境搭建(二)

参考文章 penHarmony南向开发笔记&#xff08;一&#xff09;开发环境搭建 OpenHarmony&#xff08;鸿蒙南向开发&#xff09;——标准系统移植指南&#xff08;一&#xff09; OpenHarmony&#xff08;鸿蒙南向开发&#xff09;——小型系统芯片移植指南&#xff08;二&…

拟声 0.60.0 | 拟态风格音乐播放器,支持B站音乐免费播放

「拟声」是一款音乐播放器&#xff0c;不仅支持音视频的本地播放&#xff0c;还提供了账号注册功能&#xff0c;登录后可享受自动同步歌单、歌词等。它支持播放绝大多数音频格式&#xff0c;具备固定输出采样率、独占输出、内置均衡器和音调调整等功能。同时&#xff0c;它也支…

word文档中的文档网格——解决相同行间距当显示出不同行间距的情况

1 问题 被一个行间距调疯了&#xff0c;就是样式改了没用&#xff0c;格式刷刷了没用。就是肉眼可以看出行间距完全不一样。 2 解决方法 1&#xff09;修改论文正文(即出现问题文本的样式)样式&#xff1a;样式>修改>格式>段落>缩进和间距>取消"如果定义了…

linux nginx maccms管理后台无法进入页面不存在和验证码不显示的问题

windows中运行maccms非常顺利&#xff0c;轻松搭建了。并一切正常。而我在linux中搭建缺遇到了一个非常奇怪的问题。进入管理后台&#xff0c;明明"admin.php"(比如重命名成a.php)的页面是存在的&#xff0c;访问时缺提示页面不存在&#xff01;稍后就自动跳到首页了…

简单使用linux

1.1 Linux的组成 Linux 内核&#xff1a;内核是系统的核心&#xff0c;是运行程序和管理 像磁盘和打印机等硬件设备的核心程序。 文件系统 : 文件存放在磁盘等存储设备上的组织方法。 Linux 能支持多种目前浒的文件系统&#xff0c;如 ext4 、 FAT 、 VFAT 、 ISO9660 、 NF…

pikachu靶场--目录遍历和敏感信息泄露

pikachu靶场—目录遍历和敏感信息泄露 目录遍历 概述 在web功能设计中,很多时候我们会要将需要访问的文件定义成变量&#xff0c;从而让前端的功能便的更加灵活。 当用户发起一个前端的请求时&#xff0c;便会将请求的这个文件的值(比如文件名称)传递到后台&#xff0c;后台再…

MyBatis-plus sql拦截器

因为业务需求&#xff0c;重新写了一套数据权限。项目中用的是mybtis-plus&#xff0c;正好MyBatis-Plus提供了插件数据权限插件 | MyBatis-Plus&#xff0c;那就根据文档来实现这个需求。 实现&#xff1a; 实现MultiDataPermissionHandler 首先创建MultiDataPermissionHan…

硬件-射频-PCB-常见天线分类-ESP32实例

文章目录 一&#xff1a;常见天线1.1 PCB天线①蓝牙模块的蛇形走线-天线②倒F天线-IFA&#xff1a;③蛇形倒F天线-MIFA④立体的倒F天线-PIFA 1.2 实例示意图1.21 对数周期天线(LPDA):1.22 2.4GHZ的八木天线&#xff1a;1.23 陶瓷天线&#xff1a;1.24 外接天线&#xff1a; 二&…

Gitlab-runner 修改默认的builds_dir并使用custom_build_dir配置

gitlab-runner 修改默认的builds_dir并使用custom_build_dir配置 1. 说明2. 实操&#xff08;以docker执行器为例&#xff09;2.1 修改默认的builds_dir2.1.1 调整gitlab-runner的配置文件2.1.2 CI文件 2.2 启用custom_build_dir2.2.1 调整gitlab-runner的配置文件2.2.2 CI文件…

WPF+Prism View与ViewModel绑定

1、开发环境&#xff0c;Win10VS2022.NET8Prism.DryIoc&#xff08;9.0.537&#xff09;或Prism.Unity。 2、通过NuGet安装Prism.DryIoc&#xff08;9.0.537&#xff09;或Prism.Unity。 2.1、创建ViewModels文件夹用于存放ViewModel文件、创建Views文件夹存放View文件。 将…