數據結構與算法學習筆記----快速冪

數據結構與算法學習筆記----快速冪

@@ 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 aibi??modpi?的值

輸入格式

第一行包含整數 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 aibi??modpi?的值。

每個結果占一行。

數據范圍

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?,pi?2×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?+?+2xk?modp=a2x1?a2x2??a2xk?modp=(a2x1?modp)?(a2x2?modp)?(a2xk?modp)?

在代碼中,我們也無需對 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 0p?1之間的逆元。

乘法逆元的定義

若整數 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) ba?a×x(modm),則稱 x x x b b b m m m的乘法逆元,記為 b ? 1 ( m o d m ) b^{-1}(mod \; m) b?1(modm)

b b b存在乘法逆元的充要條件是 b b b與模數 m m m互質,當模數 m m m為質數時, b m ? 2 b^{m - 2} bm?2即為 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?,pi?2?109

思路

主要的難點是定義比較繞,我們可以對定義的式子進行一些變形

a b ≡ a × x ( m o d m ) (1) \frac{a}{b} \equiv a \times x (mod \; m) \tag{1} ba?a×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) am?11(modm)

那么對費馬小定理的這個公式進行變形,拆分次方可得 a ? a m ? 2 ≡ 1 ( m o d m ) a \cdot a^{m - 2} \equiv 1 \; (mod \; m) a?am?21(modm),我們就能直接得到 a a a的乘法逆元是 a m ? 2 a^{m - 2} am?2

因此問題轉換為求 a m ? 2 a^{m - 2} am?2,也就是應用上面的快速冪。

需要注意的是題目雖然保證了 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.pswp.cn/web/64861.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/64861.shtml
英文地址,請注明出處:http://en.pswp.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;集成開…