min_25篩學習筆記+牛客多校02E

本來沒有學習這種較難的算法的想法的,因為比賽也做不到這種難度的題, 但是最近打牛客多校02,有一題要求 [1,n][1,n][1,n] 中素數的個數,我以為是像莫反一樣容斥,但是后面感覺不行。賽后知道是用 min_25 篩來求,賽時過了一車,因此我也不得不學習這個算法了。

我打算拿洛谷里面的模板來舉例。

就是給你積性函數
f(x)={kx=1g(x)=∑i=0kaixix=pc,p∈prime,c≥1f(x1)f(x2)(x1,x2)=1f(x)=\begin{cases} k & x=1 \\ g(x)=\sum_{i=0}^ka_ix^i & x=p^c,p\in prime,c\ge 1 \\ f(x_1)f(x_2) & (x_1,x_2)=1 \end{cases} f(x)=????kg(x)=i=0k?ai?xif(x1?)f(x2?)?x=1x=pc,pprime,c1(x1?,x2?)=1?

然后讓你求
∑i=1nf(i)\sum_{i=1}^nf(i) i=1n?f(i)

其中 n≤1013n\le10^{13}n1013

在牛客多校的那個題中,也有 n≤109n\le 10^9n109

一般來講,想解決這種問題都要從 iii 最小的質因子入手,因為一個數要么是質數,要么最小的質因子 ≤n0.5\le n^{0.5}n0.5,而 n0.5n^{0.5}n0.5 一般都是10610^6106~10710^7107 數量級,可以直接用線性篩得到,也能全部枚舉一次。因此總的思路大概就是先求出 ∑i=1ng(i)\sum_{i=1}^ng(i)i=1n?g(i) 然后通過枚舉最小的質因子來修正有超過一個質因子的數的貢獻,這樣能夠很好的解決大質數無法直接得到的問題。

如果沒有學過要怎么求 ∑i=1nik\sum_{i=1}^ni^ki=1n?ik,可以看我的博客

基于這個大的思路,我自己感覺 min_25 篩的思路是非常自然,很容易就能記下來。

對于式子
∑i=1nf(i)\sum_{i=1}^nf(i) i=1n?f(i)

先將 111 去掉,因為其不包含任何素數,計算的時候容易出現奇怪的錯誤,雖然按照積性函數的定義, f(1)=1f(1)=1f(1)=1

于是變成
f(1)+∑i=2nf(i)f(1)+\sum_{i=2}^nf(i) f(1)+i=2n?f(i)

自己感覺 min_25 篩很關鍵的一點是其能夠快速求出
g(b)=∑p∈prime,p≤bpkg(b)=\sum_{p\in prime,p\le b}p^kg(b)=pprime,pb?pk其中 b=?na?b=\left\lfloor \frac{n}{a} \right\rfloorb=?an??,這也意味著 bbb 的個數只有 O(n0.5)O(n^{0.5})O(n0.5)

雖然只能求出若干次方的和,但只要把每一項都求一次就可以得到原函數了。

然后剩下的和數就能通過枚舉小最小的質因子來考慮

因此 min_25 篩有兩步,分別是求出質數出的函數和,求出所有的函數和

第一步:求出質數處的函數和

這一步的思路就是像我剛才說的,先求出所有的函數和,然后通過枚舉最小的質因子把和數的貢獻剪掉即可。

我們從小到大枚舉素數,并且同時維護所有的 g(b)g(b)g(b),假設當前的素數為 ppp,假設其為第 iii 個素數。那么顯然有 p≤n0.5p\le n^{0.5}pn0.5。 我們記第 iii 個素數為 pip_ipi?

對于 g(b)g(b)g(b),我們應該減去 111 ~ bbb 中最小質因子為 ppp 的和數,如果我們直接固定 ppp,也就是只需要考慮 111 ~ ?bp?\left\lfloor \frac{b}{p} \right\rfloor?pb?? 中最小質因子 ≥p\ge pp 的數,然后你就會發現這個數剛好就是 g(?bp?)?∑j=1i?1pjkg(\left\lfloor \frac{b}{p} \right\rfloor)-\sum_{j=1}^{i-1}p_j^kg(?pb??)?j=1i?1?pjk?,(因為 ggg 函數中包含 <p<p<p 的素數)后者只需要線性篩的時候預處理即可。

然后容斥完以后我們就可以得到所有的 g(b)g(b)g(b) 了。

第二步:求出原函數

這一步的思路是也是拆分成質數貢獻與和數貢獻,質數貢獻可以直接通過前面的 ggg 函數得到,和數貢獻可以通過枚舉最小質因子不斷遞歸求解。

我們另 S(n,x)S(n,x)S(n,x) 表示 111 ~ nnn 中最小質因子 >px>p_x>px? 的數的貢獻之和,我們認為質數本身就是其最小質因子。

然后有
S(n,x)=g(n)?∑i=1xf(pi)+∑pic≤n,i>xf(pic)(S(?npic?,i+1)+[c>1])S(n,x)=g(n)-\sum_{i=1}^xf(p_i)+\sum_{p_i^c\le n,i>x}f(p_i^c)(S(\left\lfloor\frac{n}{p_i^c}\right\rfloor,i+1)+[c>1]) S(n,x)=g(n)?i=1x?f(pi?)+pic?n,i>x?f(pic?)(S(?pic?n??,i+1)+[c>1])

因為 c>1c>1c>1 的時候 picp_i^cpic? 本身也能夠產生貢獻。

以下是我洛谷模板的代碼

#include <bits/stdc++.h>
#define ll long long
using namespace std;const int mod = 1e9 + 7;int power(int a, int b) {int ret = 1;while (b) {if (b & 1) ret = 1ll * ret * a % mod;a = 1ll * a * a % mod; b >>= 1;}return ret;
}const int inv2 = power(2, mod - 2), inv3 = power(3, mod - 2);
const int N = 1e6 + 10;int cnt, p[N]; bool v[N];
int sp1[N], sp2[N];
ll n, Sqr, w[N];
int tot, g1[N], g2[N], ind1[N], ind2[N];void pre(int n) {v[1] = 1;for (int i = 2; i <= n; i++) {if (!v[i]) {p[++cnt] = i;sp1[cnt] = (sp1[cnt - 1] + i) % mod;sp2[cnt] = (sp2[cnt - 1] + 1ll * i * i) % mod;}for (int j = 1; j <= cnt && i * p[j] <= n; j++) {v[i * p[j]] = 1;if (i % p[j] == 0) break;}}
}int S(ll x, int y) {if (p[y] >= x) return 0;ll k = x <= Sqr ? ind1[x] : ind2[n / x];int ans = (1ll * g2[k] - g1[k] + mod - (sp2[y] - sp1[y]) + mod) % mod;for (int i = y + 1; i <= cnt && 1ll * p[i] * p[i] <= x; i++) {ll pe = p[i];for (int e = 1; pe <= x; e++, pe *= p[i]) {ll xx = pe % mod;ans = (ans + xx * (xx - 1) % mod * (S(x / pe, i) + (e != 1)) % mod) % mod;}}return ans % mod;
}int main() {// freopen("in.in", "r", stdin);ios::sync_with_stdio(false);cin.tie(nullptr);cin >> n;Sqr = sqrt((long double)n);pre(Sqr);for (ll i = 1, j; i <= n; i = j + 1) {j = n / (n / i);w[++tot] = n / i;int now = w[tot] % mod;g1[tot] = 1ll * now * (now + 1) / 2 % mod - 1;g2[tot] = 1ll * now * (now + 1) / 2 % mod * (2 * now + 1) % mod * inv3 % mod - 1;if (n / i <= Sqr) ind1[n / i] = tot;else ind2[n / (n / i)] = tot;}for (int i = 1; i <= cnt; i++) {for (int j = 1; j <= tot && 1ll * p[i] * p[i] <= w[j]; j++) {ll k = w[j] / p[i] <= Sqr ? ind1[w[j] / p[i]] : ind2[n / (w[j] / p[i])];g1[j] = (g1[j] - 1ll * p[i] * (g1[k] - sp1[i - 1] + mod) % mod + mod) % mod;g2[j] = (g2[j] - 1ll * p[i] * p[i] % mod * (g2[k] - sp2[i - 1] + mod) % mod + mod) % mod;}}cout << (S(n, 0) + 1) % mod << "\n";return 0;
}

時間復雜度

第一步的時間復雜度是 O(n0.75ln?n)O(\frac{n^{0.75}}{\ln n})O(lnnn0.75?) 是沒有爭議的,有一些人底下寫的是 log?\loglog 也是對的,因為只有常數倍的差別

對于第一重循環,因為素數的密度的是 1ln?n\frac{1}{\ln n}lnn1?,所以可以提出一個 1ln?n\frac{1}{\ln n}lnn1?

然后變為這個式子 O(∑i=1ni+ni)=O(∑i=1nni)=O(n∑i=1n1i)=O(n∫1n1xdx)=O(nn∣1n)=O(n0.75)O(\sum_{i=1}^{\sqrt n}\sqrt i+\sqrt \frac{n}{i})=O(\sum_{i=1}^{\sqrt n}\sqrt \frac{n}{i})=O(\sqrt n\sum_{i=1}^{\sqrt n}\sqrt \frac{1}{i})=O(\sqrt n\int_{1}^{n} \frac{1}{\sqrt x}\, dx)=O(\sqrt n\sqrt n|_{1}^{\sqrt n})=O(n^{0.75})O(i=1n??i?+in??)=O(i=1n??in??)=O(n?i=1n??i1??)=O(n?1n?x?1?dx)=O(n?n?1n??)=O(n0.75)

第二步我在網上沒有找到具體的證明,自己也感覺比較難證明,但是聽說是一般情況是 O(n1?δ)O(n^{1-\delta})O(n1?δ),但是如果 n≤1013n\le 10^{13}n1013,就滿足 O(n0.75ln?n)O(\frac{n^{0.75}}{\ln n})O(lnnn0.75?),基本適合OI的范圍。

學完 min_25 篩,就會發現前面那個求素數個數的問題實在是太簡單了,連 SSS 函數都不用算,直接把 ggg 函數計算以下就行了,然后把多項式設置為 f(x)=1f(x)=1f(x)=1 即可。

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

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

相關文章

FunASR Paraformer-zh:高效中文端到端語音識別方案全解

項目簡介 FunASR 是阿里巴巴達摩院開源的端到端語音識別工具箱,集成了多種語音識別、語音活動檢測(VAD)、說話人識別等模塊。其中 paraformer-zh 和 paraformer-zh-streaming 是針對中文語音識別任務優化的端到端模型,分別適用于離線和流式場景。Paraformer 采用并行 Tran…

數據結構自學Day9: 二叉樹的遍歷

一、二叉樹的遍歷“遍歷”就是按某種規則 依次訪問樹中的每個節點&#xff0c;確保 每個節點都被訪問一次且只訪問一次遍歷&#xff1a;前序 中序 后序&#xff08;深度優先&#xff09;&#xff0c;層序&#xff08;廣度優先&#xff09;類型遍歷方法特點深度優先遍歷前序、中…

Leetcode(7.16)

求二叉樹最小深度class Solution {public int minDepth(TreeNode root) {if (root null) {return 0;}Queue<TreeNode> queue new LinkedList<>();queue.offer(root);int depth 0;while (!queue.isEmpty()) {depth;int levelSize queue.size();for (int i 0; i…

Go從入門到精通(25) - 一個簡單web項目-實現鏈路跟蹤

Go從入門到精通(25) 一個簡單web項目-實現鏈路跟蹤 文章目錄Go從入門到精通(25)前言為什么需要分布式鏈路跟蹤&#xff1f;go實現鏈路跟蹤搭建zipkin 服務安裝依賴添加tracing包&#xff0c;OpenTelemetry 和Zipkin在 Gin 中集成 OpenTelemetry 中間件log包添加獲取traceId方法…

2025年最新秋招java后端面試八股文+場景題

一、Java核心八股文&#xff08;2025年最新版&#xff09;1. Java基礎HashMap vs ConcurrentHashMapHashMap&#xff1a;非線程安全&#xff0c;JDK1.8后采用數組鏈表/紅黑樹&#xff0c;擴容時可能死循環&#xff08;JDK1.7&#xff09;。ConcurrentHashMap&#xff1a;JDK1.8…

esp32 sd卡

ref&#xff1a; platform io & arduino Boards — PlatformIO latest documentation https://github.com/espressif/arduino-esp32/blob/master/libraries/SD_MMC/README.md SD 卡實驗 | 極客俠GeeksMan GitHub - fabianoriccardi/ESPLogger: An Arduino library pro…

Java學習--------消息隊列的重復消費、消失與順序性的深度解析?

在 Java 分布式系統開發中&#xff0c;消息隊列的應用已十分普遍。但隨著業務規模擴大&#xff0c;消息的重復消費、意外消失、順序錯亂等問題逐漸成為系統穩定性的隱患。本文將從 Java 開發者的視角&#xff0c;深入分析這三大問題的產生原因、業務后果&#xff0c;并結合具體…

【Oracle】centos7離線靜默安裝oracle11g(p13390677_112040)

博文地址&#xff1a;https://blog.csdn.net/gitblog_06670/article/details/142569814 倉庫地址&#xff1a;https://gitcode.com/Open-source-documentation-tutorial/31eb1/?utm_sourcedocument_gitcode&indexbottom&typecard 參考安裝地址&#xff1a; 收費版&…

智能設備暢想

### 智能設備暢想 突然想到了一個好主意 因為最近在查無人機的相關資料&#xff08;很早之前就想搞個無人機玩玩但始終沒有買&#xff09; 在了解自組裝方面的內容時&#xff0c;和AI溝通了下 正好之前組裝的 小智AI 基本上已經完善了&#xff0c;也正在考慮其在其他方向拓展的…

SpringAI——ChatModel

我的前面一篇文章&#xff08;SpringAI——ChatClient配置與使用&#xff09;中講了ChatClient&#xff0c;它是一個構建于 ChatModel 之上的高層封裝&#xff0c;它提供了更豐富的對話交互能力。可以這么說ChatModel相當于發動機&#xff0c;ChatClient相當于一臺含有發動機、…

Zabbix監控K8S的PV信息詳細教程!

文將介紹如何使用Zabbix自定義鍵值腳本方式監控K8S的PV卷狀態等信息。 在Kubernetes (K8S) 中&#xff0c;PersistentVolume (PV) 是集群中的一個抽象層&#xff0c;它代表了底層存儲資源&#xff0c;例如網絡存儲系統&#xff08;如NFS、Ceph、GlusterFS等&#xff09;或本地存…

wx小程序原生開發使用高德地圖api

第一步&#xff1a;注冊高德地圖api的key第二步&#xff1a;下載amap-wx.js 放到項目的某個目錄第三步&#xff1a;配置app.json&#xff08;必須&#xff0c;因為需要定位功能&#xff0c;&#xff09;"requiredPrivateInfos": ["getLocation"],"per…

如何通過mac的前24bit,模糊確認是那一臺什么樣的設備

MAC Address Lookup - MAC/OUI/IAB/IEEE Vendor Manufacturer Search Wireshark ? Go Deep 上面這兩個網址提供了&#xff0c;正對mac 的前24位&#xff0c;查找對應的網絡設備廠商信息&#xff0c;可以讓我們在運維過程中模糊的判斷大約是什么型號的設備 使用macvendorloo…

【爬蟲】04 - 高級數據存儲

爬蟲04 - 高級數據存儲 文章目錄爬蟲04 - 高級數據存儲一&#xff1a;加密數據的存儲二&#xff1a;JSON Schema校驗三&#xff1a;云原生NoSQL(了解)四&#xff1a;Redis Edge近端計算(了解)五&#xff1a;二進制存儲1&#xff1a;Pickle2&#xff1a;Parquet一&#xff1a;加…

UDP和TCP的主要區別是什么?

在網絡通信中&#xff0c;TCP&#xff08;傳輸控制協議&#xff09;和UDP&#xff08;用戶數據報協議&#xff09;是兩種核心的傳輸層協議。它們各自的特點和應用場景截然不同&#xff0c;理解兩者的區別對于選擇合適的通信方式至關重要。本文將通過幾個關鍵點&#xff0c;用簡…

Softhub軟件下載站實戰開發(十八):軟件分類展示

Softhub軟件下載站實戰開發&#xff08;十八&#xff09;&#xff1a;軟件分類展示 &#x1f5a5;? 在之前文章中&#xff0c;我們實現了后臺管理相關部分&#xff0c;本篇文章開始我們來實現用戶端頁面&#xff0c;由于內網使用&#xff0c;不需要sso優化等特性&#xff0c;我…

linux--------------------BlockQueue的生產者消費模型

1.基礎BlockingQueue的生產者消費模型 1.1 BlockQueue 在多線程編程中阻塞隊列是一種常用于實現生產者和消費者模型的數據結構&#xff0c;它與普通的隊列區別在于&#xff0c;當隊列為空時&#xff0c;從隊列獲取元素的操作將被阻塞&#xff0c;直到隊列中放入了新的數據。當…

堆排序算法詳解:原理、實現與C語言代碼

堆排序&#xff08;Heap Sort&#xff09;是一種高效的排序算法&#xff0c;利用二叉堆數據結構實現。其核心思想是將待排序序列構造成一個大頂堆&#xff08;或小頂堆&#xff09;&#xff0c;通過反復調整堆結構完成排序。下面從原理到實現進行詳細解析。一、核心概念&#x…

SSM框架——注入類型

引用類型的注入&#xff1a;Setter方法簡單類型的注入&#xff1a;定義簡單實例和方法在配置文件中對bean進行配置&#xff0c;使用porperty屬性 值用value&#xff08;ref是用來獲取bean的&#xff09;構造器方法&#xff1a;構造器方法中需要寫name&#xff0c;這樣程序就會耦…

信息學奧賽一本通 1552:【例 1】點的距離

【題目鏈接】 ybt 1552&#xff1a;【例 1】點的距離 【題目考點】 1. 最近公共祖先&#xff08;LCA&#xff09;&#xff1a;倍增求LCA 知識點講解見&#xff1a;洛谷 P3379 【模板】最近公共祖先&#xff08;LCA&#xff09; 【解題思路】 首先用鄰接表保存輸入的無權圖…