數論——質數和合數及求質數

質數、合數和質數篩

  • 質數和合數及求質數
    • 試除法判斷質數
    • Eratosthenes篩選法(埃氏篩)
    • 線性篩(歐拉篩)
  • 質數有關OJ列舉
    • P1835 素數密度 - 洛谷
    • 簡單的哥赫巴德猜想和cin優化

質數和合數及求質數

一個大于 1 的自然數,除了 1 和它自身外,不能被其他自然數整除的數叫做質數;否則稱為合數。其中,質數又稱素數。有的資料用的詞不同,但質數和素數其實是一回事。

規定 1 既不是質數也不是合數。

試除法判斷質數

  • 對于一個數 x x x,根據定義,可以從 [ 2 , x ? 1 ] [2, x - 1] [2,x?1] 一個一個嘗試,判斷 x x x 能否被整除。

但是,沒有必要每一個都去判斷。因為 a a a 如果是 x x x 的約數,那么 x / a x / a x/a 也是 x x x 的約數。因此,我們僅需判斷較小的 a a a 是否是 x x x 的約數,沒有必要再去看看 x / a x / a x/a。那么,僅需枚舉到 x \sqrt{x} x ? 即可。

試除法實現:

bool prim(int x) {if (x < 2)return false;for (int i = 2; i <= x / i; i++)//i*i<=x,所以i<=x/i,這是防溢出寫法if (x % i == 0)return false;return true;
}

時間復雜度:因為是枚舉到 n \sqrt{n} n ?,所以時間復雜度為 O ( N ) O(\sqrt{N}) O(N ?)

模板題:

P5736 【深基7.例2】質數篩 - 洛谷

#include<bits/stdc++.h>
using namespace std;bool prim(int x) {if (x < 2)return false;for (int i = 2; i <= x / i; i++)if (x % i == 0)return false;return true;
}int main() {int n; cin >> n;for (int x = 0; n--;) {cin >> x;if (prim(x))cout << x << ' ';}return 0;
}

Eratosthenes篩選法(埃氏篩)

模板題:P3383 【模板】線性篩素數 - 洛谷

在很多場景我們需要知道[2, n]內有多少個質數,或正數、倒數第 k k k個質數是多少。 n n n 很有可能特別大,此時傳統的試除法一個一個判斷顯然會很慢甚至無法在規定時間內完成判斷。因此需要使用其他算法來篩選出指定范圍內的質數。

Eratosthenes篩選法基本思想:質數的倍數一定不是質數。

實現方法:用一個長度為 N + 1 N+1 N+1 的數組vis保存信息(0 表示質數,1 表示非質數),先假設所有的數都是質數(初始化為 0),從小到大枚舉每一個質數 x x x,把 x x x 的倍數都標記為非質數(置為 1)。當從小到大掃描時掃描到一個數 x x x ,若它尚未被標記,則它不能被 2 ~ x ? 1 2 \sim x-1 2x?1 之間的任何數整除,該數就是質數。

整數 1 特殊處理即可。在篩數的時候可以從 x 2 x^2 x2開始篩,因為小于 x x x的合數是被篩選過的。

//Eratosthenes篩(埃氏篩)
void get_prim(vector<int>&vis, vector<int>&ans) {for (size_t i = 2; i < vis.size(); i++) {if (vis[i])continue;//記錄素數ans.push_back(i);//從i*i開始,因為小于i的合數已經被篩掉了for (size_t j = i * i; j < vis.size(); j+=i)vis[j] = true;//篩掉合數}
}

時間復雜度(推薦直接記結論): O ( n log ? log ? n ) O(n\log\log n) O(nloglogn)。這里 n n n實際就是vis.size()

嚴謹的數學推導:埃氏篩法的時間復雜度的詳細證明-CSDN博客

P3383 【模板】線性篩素數 - 洛谷參考程序(埃氏篩):

#include<bits/stdc++.h>
using namespace std;void Eratosthenes(vector<bool>& vis, vector<int>& ans) {for (size_t i = 2; i < vis.size(); i++) {if (vis[i])continue;ans.push_back(i);for (size_t j = i * i; j < vis.size(); j += i)vis[j] = true;}
}int main() {int n, q,num;scanf("%d %d", &n, &q);vector<bool>vis(n + 1, false);vector<int>ans;Eratosthenes(vis, ans);//埃氏篩while (q--) {scanf("%d", &num);cout << ans[num - 1] << endl;}return 0;
}

線性篩(歐拉篩)

線性篩法,又稱歐拉篩法。在埃氏篩法中,它會將一個合數重復多次標記。如果能讓每個合數都只被標記一次,那么時間復雜度就可以降到 O ( n ) O(n) O(n)

我們的做法是,讓每一個合數被它的最小質因數篩掉

void get_prim(vector<int>& vis, vector<int>& ans) {for (size_t i = 2; i < vis.size(); i++) {if (!vis[i])//被標記為true時是合數ans.push_back(i);//1uLL是為了讓size_t強制轉換成unsigned long long防止溢出for (size_t j = 0; 1uLL * i * ans[j] < vis.size(); j++) {//篩掉合數vis[i * ans[j]] = true;//i是質數的倍數時停止,當i正好為最后一個質數時循環終止if (i % ans[j] == 0)break;}}
}

i%ans[j]==0這個判定條件能讓每一個合數被自己的最小質因數篩掉。

  1. 如果 i 是合數,枚舉到最小質因數的時候跳出循環
  2. 如果 i 是質數,枚舉到自身時跳出循環
    注意,在篩的過程中,我們還能知道 p[j]i 的最小質因數

這個算法最多遍歷2遍數組,也就是說實際的時間復雜度是 O ( 2 n ) O(2n) O(2n)

很多和數學有關的算法都是在歐拉篩的基礎上實現(例如積性函數),因此歐拉篩很重要,需要理解這個算法的本質。

P3383 【模板】線性篩素數 - 洛谷參考程序(歐拉篩):

#include<bits/stdc++.h>
using namespace std;void Euler(vector<bool>& vis, vector<int>& ans) {for (size_t i = 2; i < vis.size(); i++) {if (!vis[i])ans.push_back(i);for (size_t j = 0; 1uLL * i * ans[j] < vis.size(); j++) {vis[i * ans[j]] = true;if (i % ans[j] == 0)break;}}
}int main() {int n, q,num;scanf("%d %d", &n, &q);vector<bool>vis(n + 1, false);vector<int>ans;Euler(vis, ans);//歐拉篩while (q--) {scanf("%d", &num);cout << ans[num - 1] << endl;}return 0;
}

質數有關OJ列舉

P1835 素數密度 - 洛谷

P1835 素數密度 - 洛谷

因為 1 ≤ L ≤ R ≤ 2 31 1\leq L\leq R\leq 2^{31} 1LR231,無論是埃氏篩還是線性篩,在空間上會超限,在時間上遍歷 2 31 2^{31} 231 O ( n ) O(n) O(n)的算法也無法在1秒內完成。

根據試除法,求一個數 r r r是否是質數,只需枚舉 [ 1 , r ] [1, \sqrt{r}] [1,r ?]

所以代碼思路:

  • 先找出 [ 1 , R ] [1, \sqrt{R}] [1,R ?]內的質數,再利用這些質數將 [ L , R ] [L,R] [L,R]內的合數標記。 R \sqrt{R} R ?的數據范圍是 [ 2 , 2 16 ] [2,2^{16}] [2,216] 2 16 = 65536 2^{16}=65536 216=65536,在可接受范圍內,用埃氏篩或歐拉篩都可以。
  • 找到這些質數在 [ L , R ] [L,R] [L,R]內的最小合數后,用埃氏篩的做法標記 [ L , R ] [L,R] [L,R]內的其他合數。首先需要找到質數在 [ L , R ] [L,R] [L,R]的最小倍數。
    所以整體思路是埃氏篩 + 歐拉篩。

找質數在 [ L , R ] [L,R] [L,R]內的最小倍數:假設 p ∈ [ 1 , R ] p\in [1,\sqrt{R}] p[1,R ?] p p p是質數,則 k p ≥ L kp\geq L kpL k ≥ ? L p ? k\geq \lceil\frac{L}{p}\rceil k?pL??,也就是說可以通過左端點除以質數并向上取整,再乘質數,即可得到最小倍數。即 ? L p ? × p \lceil\frac{L}{p}\rceil\times p ?pL??×p

在計算機中求 ? L p ? \lceil\frac{L}{p}\rceil ?pL??,特別是c++默認整數除法/會去除小數部分,所以可以通過對 L + ( p ? 1 ) p \frac{L+(p-1)}{p} pL+(p?1)?向下取整來間接求得 ? L p ? \lceil\frac{L}{p}\rceil ?pL??

  • L L L p p p的倍數,后面的 p ? 1 p-1 p?1對整體不構成影響;
  • 若不是,則在浮點數的視角, L p \frac{L}{p} pL?會殘留有小數部分,這一部分加上 p ? 1 p \frac{p-1}{p} pp?1?大于1,所以通過 ? L + ( p ? 1 ) p ? \lfloor\frac{L+(p-1)}{p}\rfloor ?pL+(p?1)??也能間接求得 ? L p ? \lceil\frac{L}{p}\rceil ?pL??

綜上, ? L + ( p ? 1 ) p ? = ? L p ? \lfloor\frac{L+(p-1)}{p}\rfloor=\lceil\frac{L}{p}\rceil ?pL+(p?1)??=?pL??。在代碼中可通過(L+p-1)/p*p得到質數 p p p的不小于 L L L的最小倍數。

其中需要注意的細節:

  1. L = 1 L=1 L=1,但1不是質數,所以此時需要從 L = 2 L=2 L=2開始。
  2. L ∈ [ 1 , R ] L\in [1,\sqrt{R}] L[1,R ?] L L L可能是質數。
    例如{2,3,5},要求篩掉[5,25]中的合數, ? 5 + 5 ? 1 5 ? × 5 = 5 \lfloor\frac{5+5-1}{5}\rfloor\times 5=5 ?55+5?1??×5=5,因此會把5篩掉,但5是質數不能被篩掉,因為之前較小的質數已經把部分合數給曬掉了,所以若枚舉到質數 p p p,則從 2 p 2p 2p開始篩,因此在使用埃氏篩的方法篩掉合數時可以從 max ? ( 2 p , ? L + ( p ? 1 ) p ? ) \max(2p,\lfloor\frac{L+(p-1)}{p}\rfloor) max(2p,?pL+(p?1)??)開始。
  3. 因為 R R R是有可能到 2 31 2^{31} 231,數組不可能開這么大,但可以通過小區間[0,R-L]來存儲[L,R]的結果,再開一個 10 6 10^6 106的數組勉強能接受。
  4. 因為數據量整體過大,只有放棄vector轉用一般的數組才能不超時。
#include<bits/stdc++.h>
using namespace std;typedef long long LL;
const int N = 1e6 + 10;
bool vis1[N], vis2[N];//因為超時,不得不換成普通數組
int ans[N], pans;
int L, R;void get_prim() {size_t n = sqrt(R);for (size_t i = 2; i <= n; i++) {if (!vis1[i])ans[++pans]=i;for (size_t j = 1; 1ull * i * ans[j] <= n; j++) {vis1[i * ans[j]] = 1;if (i % ans[j] == 0)break;}}
}int main() {cin >> L >> R;get_prim();L = L == 1 ? 2 : L;for (int i = 1; i <= pans;i++) {int x = ans[i];for (LL i = max(x * 2, (L + x - 1) / x * x);i<=R; i+=x) {vis2[i - L] = 1;}}int cnt = 0;for (int i = L; i <= R; i++) if (!vis2[i - L])++cnt;cout << cnt;return 0;
}

簡單的哥赫巴德猜想和cin優化

UVA543 Goldbach’s Conjecture - 洛谷

1622:Goldbach’s Conjecture

這題是UVA上的題,但可以在信奧網站提交。

素數篩制表,然后查表即可。因為這個猜想至今仍然沒有找到一個反例,所以直接找即可。

因為數據量過大,用cin輸入時需要使用優化手段,或直接用scanf。而且不能用endl

#include<bits/stdc++.h>
using namespace std;const int N = 1e6 + 1;
bool vis[N];
int ans[N], pans;void get_prim() {for (int i = 2; i < N; i++) {if (!vis[i])ans[++pans] = i;for (int j = 1; 1ull*i * ans[j] < N; j++) {vis[i * ans[j]] = 1;if (i % ans[j] == 0)break;}}
}int main() {ios::sync_with_stdio(0);cin.tie(0);//不用這個對cin進行優化會超時//cout.tie(0);//這個有沒有都不影響get_prim();int n;while (cin>>n, n) {for (int i = 1; i <= pans &&ans[i]<n; i++) {if (!vis[n - ans[i]]) {cout << n << " = " << ans[i] << " + " << n - ans[i] << "\n";break;}}}return 0;
}

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

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

相關文章

多商戶系統源碼性能調優實戰:從瓶頸定位到高并發架構設計!

在電商業務爆發式增長的今天&#xff0c;多商戶系統作為支撐平臺方、入駐商家和終端消費者的核心樞紐&#xff0c;其性能表現直接決定了商業變現效率。當你的商城在促銷期間崩潰&#xff0c;損失的不僅是訂單&#xff0c;更是用戶信任。 本文將深入剖析多商戶系統源碼性能優化的…

JDBC連不上mysql:Unable to load authentication plugin ‘caching_sha2_password‘.

最近為一個spring-boot項目下了mysql-9.3.0&#xff0c;結果因為mysql版本太新一直報錯連不上。 錯誤如下&#xff1a; 2025-06-01 16:19:43.516 ERROR 22088 --- [http-nio-8080-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispat…

超標量處理器設計6-指令解碼

1. 指令緩存 指令緩存本質上是一個FIFO, 它能夠將指令按照程序中指定的順序存儲起來&#xff0c;這樣指令在解碼的時候&#xff0c;仍然可以按照程序中指定的順序進行解碼。指令緩存是超標量處理器中必須的部件&#xff0c;其原因有兩個&#xff1a; 1. 每周期可以取指的個數大…

基于 HT for Web 輕量化 3D 數字孿生數據中心解決方案

一、技術架構&#xff1a;HT for Web 的核心能力 圖撲軟件自主研發的 HT for Web 是基于 HTML5 的 2D/3D 可視化引擎&#xff0c;核心技術特性包括&#xff1a; 跨平臺渲染&#xff1a;采用 WebGL 技術&#xff0c;支持 PC、移動端瀏覽器直接訪問&#xff0c;兼容主流操作系統…

【Linux】shell的條件判斷

目錄 一.使用邏輯運算符判定命令執行結果 二.條件判斷方法 三.判斷表達式 3.1文件判斷表達式 3.2字符串測試表達式 3.3整數測試表達式 3.4邏輯操作符 一.使用邏輯運算符判定命令執行結果 && 在命令執行后如果沒有任何報錯時會執行符號后面的動作|| 在命令執行后…

【Python辦公】Excel簡易透視辦公小工具

目錄 專欄導讀1. 背景介紹2. 功能介紹3. 庫的安裝4. 界面展示5. 使用方法6. 實際應用場景7. 優化方向完整代碼總結專欄導讀 ?? 歡迎來到Python辦公自動化專欄—Python處理辦公問題,解放您的雙手 ?????? 博客主頁:請點擊——> 一晌小貪歡的博客主頁求關注 ?? 該系…

HarmonyOS鴻蒙與React Native的融合開發模式以及能否增加對性能優化的具體案例

鴻蒙與React Native的融合開發模式 一、技術架構設計 底層適配層 通過HarmonyOS的NDK封裝原生能力&#xff08;如分布式軟總線、AI引擎&#xff09; 使用React Native的Native Modules橋接鴻蒙API&#xff08;需重寫Java/Objective-C部分為ArkTS&#xff09; 組件映射機制 …

LLaMA-Factory - 批量推理(inference)的腳本

scripts/vllm_infer.py 是 LLaMA-Factory 團隊用于批量推理&#xff08;inference&#xff09;的腳本&#xff0c;基于 vLLM 引擎&#xff0c;支持高效的并行推理。它可以對一個數據集批量生成模型輸出&#xff0c;并保存為 JSONL 文件&#xff0c;適合大規模評測和自動化測試。…

麥克風和電腦內播放聲音實時識別轉文字軟件FunASR整合包V5下載

我基于FunASR制作的實時語音識別轉文字軟件當前更新到V5版本。軟件可以實時識別麥克風聲音和電腦內播放聲音轉為文字。 FunASR軟件介紹 FunASR 是一款基礎語音識別工具包和開源 SOTA 預訓練模型&#xff0c;支持語音識別、語音活動檢測、文本后處理等。 我使用FunASR制作了一…

子串題解——和為 K 的子數組【LeetCode】

謹記&#xff1a; 數組不是單調的話&#xff0c;不要用滑動窗口&#xff0c;考慮用前綴和 寫法一&#xff1a;兩次遍歷 代碼的核心思想是通過 前綴和 和 哈希表 來高效地統計符合條件的子數組個數。具體步驟如下&#xff1a; 計算前綴和數組 s&#xff1a; s[i] 表示 nums 的前…

硬件服務器基礎

1、硬件服務器基礎 2、服務器后面板 3、組件 3.1 CPU 3.2 內存 3.3 硬盤 3.4 風扇 4、服務器品牌 4.1 配置 4.2 CPU 架構 4.2.1 CPU 命名規則 4.2.2 服務器 CPU 和家用 CPU 的區別 4.2.3 CPU 在主板的位置 4.2.4 常見 CPU 安裝方式 4.3 內存中組件 4.3.1 內存的分類 4.3.1.1 …

OpenWebUI(1)源碼學習構建

1. 前言 通過docker鏡像拉取安裝就不介紹了&#xff0c;官方的命令很多。本節主要擼一擼源碼&#xff0c;所以&#xff0c;本地構建 2. 技術框架和啟動環境 后端python&#xff0c;前端svelte 環境要求&#xff1a;python > 3.11 &#xff0c;Node.js > 20.10 3. 源…

三方接口設計注意事項

前言 隨著業務系統間集成需求的增加&#xff0c;三方接口設計已成為現代軟件架構中的關鍵環節。一個設計良好的三方接口不僅能夠提供穩定可靠的服務&#xff0c;還能確保數據安全、提升系統性能并支持業務的持續發展。 一、設計原則 1. 統一接口原則 三方接口設計應遵循統一…

CSS篇-5

1. 內聯元素可以實現浮動嗎? 是的,內聯元素完全可以實現浮動。在 CSS 中,任何元素都可以被設置為浮動(float)。 當一個元素被設置了 float 屬性后,無論它本身是塊級元素還是內聯元素,它都會表現出類似于塊級元素的特性: 生成塊級框(Block-level box):浮動元素會生…

RocketMQ 學習

消息隊列 參考官方文檔&#xff1a;https://rocketmq.apache.org/zh/docs/ 基本概念 主題&#xff08;Topic&#xff09;&#xff1a;是消息傳輸和消息存儲的頂級容器&#xff0c;不是實際的消息容器&#xff0c;而是一個邏輯上的概念&#xff0c;用于區分不同業務消息的標識&…

Conda更換鏡像源教程:加速Python包下載

Conda更換鏡像源教程&#xff1a;加速Python包下載 為什么要更換conda鏡像源&#xff1f; Conda作為Python的包管理和環境管理工具&#xff0c;默認使用的是國外鏡像源&#xff0c;在國內下載速度往往較慢。通過更換為國內鏡像源&#xff0c;可以顯著提高包下載速度&#xff…

PCIe—TS1/TS2 之Polling.Active(一)

前文 訓練序列有序集用于比特對齊、符號對齊以及交換物理層參數。2.5GT/s和5GT/s速率時&#xff0c;訓練序列有序集不會加擾&#xff0c;只用8b/10b 編碼。但到8GT/s及以上速率時&#xff0c;采用128b/130b編碼&#xff0c;符號有可能加擾有可能不加擾&#xff0c;具體…

【HarmonyOS Next之旅】DevEco Studio使用指南(二十八) -> 開發云對象

目錄 1 -> 開發流程 2 -> 創建云對象 3 -> 開發云對象 4 -> 調試云對象 4.1 -> 前提條件 4.2 -> 通過本地調用方式調試云對象 4.3 -> 通過遠程調用方式調試云對象 5 -> 部署云對象 1 -> 開發流程 除去傳統的云函數&#xff0c;您還可在端云…

基于51單片機的音樂盒汽車喇叭調音量proteus仿真

地址&#xff1a; https://pan.baidu.com/s/1l3CSSMi4uMV5-XLefnKoSg 提取碼&#xff1a;1234 仿真圖&#xff1a; 芯片/模塊的特點&#xff1a; AT89C52/AT89C51簡介&#xff1a; AT89C51 是一款常用的 8 位單片機&#xff0c;由 Atmel 公司&#xff08;現已被 Microchip 收…

實驗設計與分析(第6版,Montgomery)第5章析因設計引導5.7節思考題5.8 R語言解題

本文是實驗設計與分析&#xff08;第6版&#xff0c;Montgomery著&#xff0c;傅玨生譯) 第5章析因設計引導5.7節思考題5.8 R語言解題。主要涉及方差分析&#xff0c;正態假設檢驗&#xff0c;殘差分析&#xff0c;交互作用圖。 (a) dataframe<-data.frame( Lightc(580,568…