算法與數據結構:質數、互質判定和裴蜀定理

文章目錄

        • 質數
        • 質數判定
        • 質數篩選
        • 質因數分解
        • 互質判定
        • 裴蜀定理

質數

首先回顧「質數」的定義:若一個正整數無法被除了 1 ?和它自身之外的任何自然數整除,則稱該數為質數(或素數),否則稱該正整數為合數。

根據上述定義,我們可以得知常見的質數有 2、3、5 等。另外,在整個自然數集合中,質數的分布也比較稀疏,對于一個足夠大的整數 N,不超過 N 的質數大約有
N / ln ? ( N ) N/\ln(N) N/ln(N) 個。

質數判定

常見的判定質數的方式是「試除法」,假設自然數 N 不是質數,則一定存在一對數
x, y ,使得下述條件成立:
N = x ? y 1 < x ≤ N ≤ y < N N = x · y \\ 1< x \leq \sqrt N \leq y < N N=x?y1<xN ?y<N

因此我們可以在 [ 2 , N ] [2, \sqrt N] [2,N ?] 的范圍內枚舉 x, 判斷 x 是否存在。

如果 x 存在,則 N 為合數;否則 N 為質數。該算法時間復雜度為 O ( N ) O(\sqrt N) O(N ?)
,具體代碼如下所示:

// c語言
bool judgePrime(int n) {for (int i = 2; i * i <= n; i++) {if (n % i == 0) return false;}return true;
}
def judgePrime(n):for i in range(2, int(n**0.5) + 1):if n % i == 0:return Falsereturn True
質數篩選

對于一個正整數 N,一次性求出 1~N 之間所有的質數,即為質數篩選。

顯然根據上述「質數判定」的內容,我們可以通過枚舉 1~N 的所有數,再依次使用「試除法」來判定其是否為質數,從而完成質數的篩選。但此種方法的時間復雜度過高,為 O ( N N ) O(N\sqrt N) O(NN ?)

此處將介紹經典的「Eratosthenes 篩法」,也被稱為「埃式篩」。該算法基于一個基本判斷:任意質數 x 的倍數 ( 2x,3x,… ) 均不是質數。

根據該基本判斷,我們得到如下算法過程:

  • 將 2~N中所有數標記為 0
  • 從質數 2 開始從小到大遍歷2 ~ N中所有自然數
  • 如果遍歷到一個標記為 0 的數 x ,則將其 2~N 中 x 的所有倍數標記為 1

根據上述過程,不難發現如果一個數 x 的標記為 0?,則代表這個數不是 2~(x-1) 中任何數的倍數,即 x 為質數。

接下來我們以 2~10 為例,具體過程如下所示,最終標記為橙色的數為質數:
在這里插入圖片描述
Eratosthenes 篩法」的時間復雜度為 O ( N log ? ( log ? ( N ) ) ) O(N\log(\log(N))) O(Nlog(log(N))) ,并不是最快的素數篩法,但在絕大多數的「力扣數學題」中均已夠用,且其實現代碼較為簡單,具體如下所示:

vector<int> primes, vis;
void get_primes(int n) {vis.resize(n + 1, 0);for(int i = 2; i <= n; i++) {if(vis[i] == 0) {primes.push_back(i);for(int j = i; j <= n; j += i) vis[j] = 1;}}
}
# Eratosthenes篩法def get_primes(n):"""獲取n以內的所有素數"""if n < 2:return []primes = [True] * (n + 1)primes[0] = primes[1] = Falsefor i in range(2, int(n**0.5) + 1):if primes[i]:for j in range(i * i, n + 1, i):primes[j] = Falsereturn [i for i in range(n + 1) if primes[i]]print(get_primes(100))[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]
質因數分解

根據「唯一分解定理」,任何一個大于 1 的正整數都能唯一分解為有限個質數的乘積: N = p 1 c 1 p 2 c 2 … p m c m N = p_1^{c_1}p_2^{c_2}…p_m^{c_m} N=p1c1??p2c2??pmcm??
其中 c i c_i ci? 均為正整數,而 p i p_i pi? 均為質數,且滿足 p 1 < p 2 < … < p m p_1 < p_2 < … < p_m p1?<p2?<<pm?

根據上述定理,我們只需要求出所有的 p i , c i p_i, c_i pi?,ci? ,即可完成對 N 的質因數分解。
那么如何求取 p i , c i p_i, c_i pi?,ci? 呢?首先我們考慮如何求 p 1 p_1 p1? c 1 c_1 c1?

由于 p 1 < p 2 < … < p m p_1 < p_2 < … < p_m p1?<p2?<<pm? ,且 p 1 p_1 p1? 為質數,因此不難發現, p 1 p_1 p1? 是 N 所有因子中除 1 以外最小的數。

因此我們可以枚舉 2 ~ N 2~\sqrt N 2N ?中的所有數 x,如果 N 是 x 的倍數,則 x 為 p 1 p_1 p1?。得到 p 1 p_1 p1? 后,我們可以令 N 不斷除以 p 1 p_1 p1? 直至其不再為 p 1 p_1 p1? 的倍數,則 c 1 c_1 c1? 等于除以 p 1 p_1 p1? 的總次數。

得到 p 1 p_1 p1? c 1 c_1 c1? 后,N 去除了所有的 p 1 p_1 p1?,因此 N 變為 p 2 c 2 … p m c m p_2^{c_2}…p_m^{c_m} p2c2??pmcm??。又由于 p 1 < p 2 p_1 < p_2 p1?<p2? ,因此我們繼續枚舉 x,如果再次出現 N 是 x 倍數的情況,則 x 為 p 2 p_2 p2?

不斷使用上述算法,直至循環結束。最后還需判斷 N 是否為 1,如果 N 不為 1,則 p m = N , c m = 1 p_m = N, c_m = 1 pm?=N,cm?=1

該算法的時間復雜度為 O ( l o g ( N ) ) O(log(N)) O(log(N)) ,具體代碼如下所示,大家可以配合代碼對該算法進行理解:

void divide(int n) {vector<int> p, c;for (int i = 2; i * i <= n; i++) {if (n % i == 0) {p.push_back(i);int num = 0;while(n % i == 0) num++, n /= i;c.push_back(num);}}if (n > 1) {p.push_back(n);c.push_back(1);}
}
# 質因數分解-唯一分解定理def divide(n):"""質因數分解"""i = 2factors = []while i * i <= n:print("i = ", i)print("n = ", n)if n % i:i += 1else:n //= ifactors.append(i)if n > 1:factors.append(n)return factorsprint("質因數分解-唯一分解定理")
print(divide(100))  # [2, 2, 5, 5]
互質判定

首先介紹一下「最大公約數」的概念。如果自然數 c 同時是自然數 a 和 b 的約數,即 a 和 b 同時是 c 的倍數,則 c 為 a 和 b 的公約數。

「最大公約數」就是 a 和 b 的所有公約數中最大的那一個,通常記為 g c d ( a , b ) gcd(a,b) gcd(a,b)

由此我們可以得到「互質」的判定條件,如果自然數 a,b 互質,則 g c d ( a , b ) = 1 gcd(a,b) = 1 gcd(a,b)=1

于是問題變為「如何求 g c d ( a , b ) gcd(a,b) gcd(a,b)?」

此處需要引入「歐幾里得算法」,如下所示:
? a , b ∈ N , b ≠ 0 , g c d ( a , b ) = g c d ( b , a m o d b ) \forall a,b \in N, b \neq 0, gcd(a,b) = gcd(b, a \quad mod \quad b) ?a,bN,b=0,gcd(a,b)=gcd(b,amodb)

根據上述算法,可以得到如下代碼,其時間復雜度為 O ( l o g ( a , b ) ) O(log(a,b)) O(log(a,b))

int gcd(int a, int b) {return b == 0 ? a : gcd(b, a % b);
}
裴蜀定理

a , b , x , y , m a, b, x, y, m a,b,x,y,m 是整數,則 a x + b y = m ax+by = m ax+by=m 有解當且僅當 m 是 g c d ( a , b ) gcd(a,b) gcd(a,b) 的倍數。

該定理有一個重要的推論:整數 a,b 互質的充要條件是存在整數 x,y 使 a x + b y = 1 ax+by=1 ax+by=1

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/906413.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/906413.shtml
英文地址,請注明出處:http://en.pswp.cn/news/906413.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

代碼隨想錄算法訓練營第60期第四十二天打卡

大家好&#xff0c;今天還是繼續我們的動態規劃里面的背包問題&#xff0c;前面我們主要接觸的是0-1背包和完全背包&#xff0c;其實這兩個背包問題主要就是看看每一件物品我們是否有多件&#xff0c;如果每一件物品我們只能取一次的話那這樣我們就是0-1背包&#xff0c;如果每…

第41天-Python+Qt四屏播放器開發指南

一、技術選型與工具準備 核心庫: Pyqt5:Python標準GUI庫,構建用戶界面 os / sys:文件系統操作 開發環境: pip install pyqt5 最終效果與運行 import sys from PyQt5.QtWidgets import QVBoxLayout, QHBoxLayout # 添加缺失的布局管理器 from PyQt5.QtCore impor…

upload-labs通關筆記-第12關 文件上傳之白名單GET法

目錄 一、白名單過濾 二、%00截斷 1、%00截斷原理 2、空字符 3、截斷條件 &#xff08;1&#xff09;PHP版本 < 5.3.4 &#xff08;2&#xff09;magic_quotes_gpc配置為Off &#xff08;3&#xff09;代碼邏輯存在缺陷 三、源碼分析 1、代碼審計 &#xff08;1&…

Node.js數據抓取技術實戰示例

Node.js常用的庫有哪些呢&#xff1f;比如axios或者node-fetch用來發送HTTP請求&#xff0c;cheerio用來解析HTML&#xff0c;如果是動態網頁的話可能需要puppeteer這樣的無頭瀏覽器。這些工具的組合應該能滿足大部分需求。 然后&#xff0c;可能遇到的難點在哪里&#xff1f;…

數據結構(3)線性表-鏈表-單鏈表

我們學習過順序表時&#xff0c;一旦對頭部或中間的數據進行處理&#xff0c;由于物理結構的連續性&#xff0c;為了不覆蓋&#xff0c;都得移&#xff0c;就導致時間復雜度為O&#xff08;n&#xff09;&#xff0c;還有一個潛在的問題就是擴容&#xff0c;假如我們擴容前是10…

【Unity】DOTween的常用函數解釋

DOTween插件常用函數解釋 1.DOTween.To&#xff08;通用變化動畫&#xff09; 解釋&#xff1a;將某一個值在一定的時間內變化到另一個值&#xff08;通用的函數&#xff09;&#xff0c;可用于大部分的動畫變化 使用示例&#xff1a; using UnityEngine; using DG.Tweenin…

數據結構測試模擬題(1)

1、約瑟夫問題 #include<bits/stdc.h> using namespace std; const int N25; int e[N],ne[N],head-1,idx1; int n,m; void add_to_head(int x){e[idx]x;ne[idx]head;headidx; } void add(int k,int x){e[idx]x;ne[idx]ne[k];ne[k]idx; } int main(){cin>>n>>…

Helm配置之為特定Deployment配置特定Docker倉庫(覆蓋全局配置)

文章目錄 Helm配置之為特定Deployment配置特定Docker倉庫(覆蓋全局配置)需求方法1:使用Helm覆蓋值方法2: 在Lens中臨時修改Deployment配置步驟 1: 創建 Docker Registry Secret步驟 2: 在 Deployment 中引用 Secret參考資料Helm配置之為特定Deployment配置特定Docker倉庫(覆…

BERT 作為Transformer的Encoder 為什么采用可學習的位置編碼

摘要 BERT 在位置編碼上與原始 Transformer 論文中的 sin/cos 公式不同&#xff0c;選擇了可學習&#xff08;learned&#xff09;的位置嵌入方案。本文將從 Transformer 原始位置編碼選項入手&#xff0c;分析 BERT 選擇 learned positional embeddings 的四大核心原因&#x…

【Linux 學習計劃】-- gcc、g++、動靜態庫鏈接

目錄 什么是gcc、g gcc、g 相關操作詳解 預處理、編譯、匯編、鏈接來源 動靜態鏈接是什么 結語 什么是gcc、g gcc、g其實就是編譯器&#xff0c;是幫助我們從.c或者.cc&#xff0c;.cpp文件編譯成可執行程序的 其中&#xff0c;我們如果要編譯c語言文件的話&#xff0c;…

前端讀取本地項目中 public/a.xlsx 文件中的數據 vue3

前端讀取本地項目中 public/a.xlsx 文件中的數據 vue3 項目中需要在 Vue3 項目中讀取 public/a.xlsx 文件&#xff0c;可以使用 fetch API 來獲取文件內容 一、安裝 xlsx 首先&#xff0c;你需要安裝 xlsx 庫&#xff1a; npm install xlsx二、在需要用的頁面里引入xlsx im…

MySQL:to many connections連接數過多

當你遇到 MySQL: Too many connections 錯誤時&#xff0c;意味著當前連接數已達到 MySQL 配置的最大限制。這通常是由于并發連接過多或連接未正確關閉導致的。 一、查看當前連接數 查看 MySQL 當前允許的最大連接數 SHOW VARIABLES LIKE max_connections;查看當前使用的最大…

2024年熱門AI趨勢及回顧

人工智能的崛起 2024 年可能會被銘記為人工智能不再是一種技術新奇事物&#xff0c;而是成為現實的一年。微軟、Salesforce 和 Intuit 等巨頭將人工智能融入主流企業解決方案&#xff1b;從文案寫作到數據分析&#xff0c;專門的人工智能應用程序和服務如雨后春筍般涌現&#…

LangFlow技術深度解析:可視化編排LangChain應用的新范式 -(2)流編輯器系統

Flow Editor System | langflow-ai/langflow | DeepWiki 流編輯器系統 相關源文件 流編輯器系統是 Langflow 的核心交互式組件&#xff0c;允許用戶直觀地創建、編輯和管理 LLM 驅動的應用程序。它提供了一個直觀的畫布&#xff0c;用戶可以在其中添加節點、將其與邊緣連接并…

驅動-定時-秒-字符設備

文章目錄 目的相關資料參考實驗驅動程序-timer_dev.c編譯文件-Makefile測試程序-timer.c分析 加載驅動-運行測試程序總結 目的 通過定時器timer_list、字符設備、規避競爭關系-原子操作&#xff0c;綜合運用 實現一個程序&#xff0c;加深之前知識的理解。 實現字符設備驅動框…

[Java實戰]Spring Boot整合Kafka:高吞吐量消息系統實戰(二十七)

[Java實戰]Spring Boot整合Kafka&#xff1a;高吞吐量消息系統實戰&#xff08;二十七&#xff09; 一、引言 Apache Kafka作為一款高吞吐量、低延遲的分布式消息隊列系統&#xff0c;廣泛應用于實時數據處理、日志收集和事件驅動架構。結合Spring Boot的自動化配置能力&…

Kotlin Multiplatform--04:經驗總結(持續更新)

Kotlin Multiplatform--04&#xff1a;經驗總結&#xff08;持續更新&#xff09; 引言 引言 本章用來記載筆者開發過程中的一些經驗總結 一、Ktor設置Header 在官方文檔中&#xff0c;想要設置Header的示例代碼如下&#xff1a; client.get("https://ktor.io&qu…

在 Ubuntu 系統中,將 JAR 包安裝為服務

在 Ubuntu 系統中&#xff0c;將 JAR 包安裝為服務可以通過 systemd 來實現。以下是詳細的操作步驟&#xff1a; 準備工作 確保 JAR 文件路徑和 Java 運行時環境已準備好。驗證 Java 是否可用&#xff1a; java -version創建 systemd 服務文件 systemd 的服務文件通常位于 …

電商項目-商品微服務-品牌管理微服務開發

一、功能分析 品牌管理微服務包括&#xff1a; &#xff08;1&#xff09;查詢全部列表數據 &#xff08;2&#xff09;根據ID查詢實體數據 &#xff08;3&#xff09;增加 &#xff08;4&#xff09;修改 &#xff08;5&#xff09;刪除 &#xff08;6&#xff09;分頁…

Spring Boot開發—— 整合Lucene構建輕量級毫秒級響應的全文檢索引擎

文章目錄 一、為什么選擇 Lucene?輕量級搜索的底層密碼二、核心原理:Lucene 的倒排索引2.1 倒排索引:速度之源2.2 段合并優化策略三、Spring Boot集成Lucene實戰3.1 依賴配置3.2 實體與索引設計3.3 核心索引服務(含異常處理)3.4 使用示例(測試類)四、高級優化技巧4.1 索…