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

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

@@ 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次方就是ak >>= 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.mzph.cn/web/64861.shtml

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

相关文章

爬虫代码中如何添加异常处理?

在编写爬虫代码时&#xff0c;添加异常处理是非常重要的一步&#xff0c;因为它可以帮助我们处理网络请求中可能出现的各种问题&#xff0c;比如网络连接错误、超时、解析错误等。以下是如何在Python爬虫代码中添加异常处理的示例&#xff1a; import requests from bs4 impor…

MAC环境安装(卸载)软件

MAC环境安装&#xff08;卸载&#xff09;软件 jdknode安装node&#xff0c;并实现不同版本的切换背景 卸载node从node官网下载pkg安装的node卸载用 homebrew 安装的node如果你感觉删的不够干净&#xff0c;可以再细分删除验证删除结果 jdk 1.下载jdk 先去官网下载自己需要的版…

本地LLM部署--llama.cpp

–图源GitHub项目主页 概述 llama.cpp是以一个开源项目&#xff08;GitHub主页&#xff1a;llamma.cpp&#xff09;&#xff0c;也是本地化部署LLM模型的方式之一&#xff0c;除了自身能够作为工具直接运行模型文件&#xff0c;也能够被其他软件或框架进行调用进行集成。 其…

uniapp中使用ruoyiPlus中的加密使用(crypto-js)

package.json中添加 "crypto-js": "^4.2.0", "jsencrypt": "^3.3.2",但是vue2中使用 import CryptoJS from cryptojs; 这一步就会报错 参照 参照这里&#xff1a;vue2使用CryptoJS实现信息加解密 根目录下的js文档中新增一个AESwork.…

go项目使用gentool生成model的gen.go问题

Gen Tool 是一个没有依赖关系的二进制文件&#xff0c;可以用来从数据库生成结构。 使用方法&#xff1a; go install gorm.io/gen/tools/gentoollatest在项目根目录,执行连接的数据库中指定某几张表结构生成数据库model层 gentool -dsn "root:123456tcp(localhost:330…

路由基本配置实验

路由器用于实现不同类型网络之间的互联。 路由器转发ip分组的基础是路由表。 路由表中的路由项分为直连路由项、静态路由项和动态路由项。 通过配置路由器接口的ip地址和子网掩码自动生成直连路由项。 通过手工配置创建静态路由项。 热备份路由器协议允许将由多个路由器组…

产品原型设计

&#x1f923;&#x1f923;目录&#x1f923;&#x1f923; 一、Axure原型设计&#xff08;Axure RP 9 &#xff09;1.1 软件下载安装1.2 产品原型展示1.3 产品原型下载1.4 视频课程推荐 二、磨刀原型设计2.1 软件下载安装2.2 产品原型展示2.3 产品原型下载2.4 视频课程推荐 什…

Android反编译

安卓反编译要用到三个工具&#xff0c; 工具1&#xff1a;apktool反编译出来资源文件和源码 工具2&#xff1a;d2j-dex2jar生成classes_dex2jar.jar文件工具3&#xff1a;jd-gui.exe 打开classes_dex2jar.jar文件查看java代码一、 反编译得到资源文件&#xff08;工具1&#xf…

计算机网络 (17)点对点协议PPP

一、PPP协议的基本概念 PPP协议最初设计是为两个对等节点之间的IP流量传输提供一种封装协议&#xff0c;它替代了原来非标准的第二层协议&#xff08;如SLIP&#xff09;。在TCP/IP协议集中&#xff0c;PPP是一种用来同步调制连接的数据链路层协议&#xff08;OSI模式中的第二层…

Tailwind CSS 实战:表单设计与验证实现

在 Web 开发中,表单就像是一位尽职的接待员,负责收集和验证用户的输入信息。记得在一个企业级项目中,我们通过重新设计表单交互流程,将表单的完成率提升了 42%。今天,我想和大家分享如何使用 Tailwind CSS 打造一个既美观又实用的表单系统。 设计理念 设计表单就像是在设计一…

信息系统项目管理师——第8章章 项目整合管理 笔记

8 项目整合管理&#xff08;最后反过来看&#xff09; 项目整合过程&#xff1a;①制定项目章程&#xff08;启动过程&#xff09;、②制订项目管理计划&#xff08;规划过程&#xff09;、③指导和管理项目工作、管理项目知识&#xff08;执行过程&#xff09;、④监控项目工…

MLP、CNN、Transformer 的区别解析

亲爱的小伙伴们&#x1f618;&#xff0c;在求知的漫漫旅途中&#xff0c;若你对深度学习的奥秘、Java 与 Python 的奇妙世界&#xff0c;亦或是读研论文的撰写攻略有所探寻&#x1f9d0;&#xff0c;那不妨给我一个小小的关注吧&#x1f970;。我会精心筹备&#xff0c;在未来…

WebRTC线程的启动与运行

WebRTC线程运行的基本逻辑&#xff1a; while(true) {…Get(&msg, …);…Dispatch(&msg);… }Dispatch(Message *pmsg) {…pmsg->handler->OnMessage(pmsg);… }在执行函数内部&#xff0c;就是一个while死循环&#xff0c;只做两件事&#xff0c;从队列里Get取…

CSS 学习之 padding 与图形绘制

padding 属性和 background-clip 属性配合&#xff0c;可以在有限的标签下实现一些 CSS 图形绘制效果&#xff0c;我这里举两个小例子&#xff0c;重在展示可行性。 例 1:不使用伪元素&#xff0c;仅一层标签实现大队长的“三道杠”分类图标效果。此效果在移动端比较常见&…

yolov5核查数据标注漏报和误报

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、误报二、漏报三、源码总结 前言 本文主要用于记录数据标注和模型预测之间的漏报和误报思想及其源码 提示&#xff1a;以下是本篇文章正文内容&#xff0c;…

UnityRenderStreaming使用记录(四)

测试把UnityRenderStreaming部署在docker&#xff0c;剧透一下&#xff0c;嘎了…… 当然webserver运行的妥妥的 那么打包出的程序运行log Mono path[0] /home/unity/Broadcast/Broadcast_Data/Managed Mono config path /home/unity/Broadcast/Broadcast_Data/MonoBleedingE…

salesforce addMonths()的问题

如果使用 Salesforce 的 addMonths(1) 方法&#xff0c;将 1月30日 或 1月31日 加一个月&#xff0c;都会得到 2月28日&#xff08;或 2月29日&#xff0c;如果是闰年&#xff09;。这是因为 Salesforce 的 addMonths 方法在跨月份时会自动调整日期&#xff0c;确保结果是有效日…

3. C语言 数据类型

本章目录&#xff1a; 前言&#xff1a;C语言中的数据类型分类1. 基本数据类型1.1 整数类型1.2 浮点类型1.3 字符型常量1.4 字符串常量 2. 枚举类型3. void 类型void类型的使用示例&#xff1a; 4. 类型转换4.1 隐式类型转换4.2 显式类型转换类型转换的注意事项 5. 小结 前言&a…

JUnit注解,枚举

一、JUnit注解&#xff08;Annotations&#xff09; JUnit 是 Java 中用于编写和运行单元测试的框架。JUnit 提供了许多注解&#xff0c;用于控制测试的执行顺序、测试生命周期、断言结果等。以下是一些常用的 JUnit 注解及其作用&#xff1a; 1. Test 用于标记一个方法是测…

富芮坤FR800X系列之软件开发工具链(如IDE、编译器、调试器等)

文章目录 一、IDE&#xff08;集成开发环境&#xff09;二、编译器三、调试器四、其他辅助工具五、小结 FR800x系列作为一款低功耗蓝牙芯片&#xff0c;其软件开发工具链对于开发者来说至关重要。以下是对FR800x软件开发工具链的详细介绍&#xff0c;包括IDE&#xff08;集成开…