Min 25 篩學習筆記

2022-04-29 04:48:09 字數 3076 閱讀 6331

模板

在本文中用 \(p\) 表示質數,\(p_i\) 表示第 \(i\) 個質數。

題目要我們求的是乙個積性函式的字首和。

我們可以對於 \(n\) 內的每乙個質因子進行單獨考慮。但是這樣子的複雜度顯然過大,而這很大一部分原因是因為 \(n\) 以內的質數。

因此如果我們把所有數分成質數和合數考慮,那麼在合數中的不同最小質因子個數就是 \(\frac\) 級別的了。

接下來我們設函式 \(s\), \(s(n, j) = \sum\limits_ ^ n f(i) (\min\limits_ p > p_j)\)

對這個函式進行分類討論。

質數如果我們已經得到質數字首和函式 \(q(x) = \sum\limits_^ f(i) (i \in prime)\)

那麼 \(s(n,j)\) 在質數處的和就很好算,為 \(q(n) - \sum\limits_^ f(p_i)\) (簡單容斥)。

合數在合數處答案考慮列舉每乙個數的最小質因數及他的次數,答案為 \(\sum\limits_ \sum\limits_^ f(p_k^e) (s(\frac, k) + \left[e>1\right])\)。

後面的 \(e>1\) 表示如果 \(k\) 次數不為 \(1\),那麼就還要再加 \(f(p_k^e)\),因為 \(s\) 是不算為 \(1\) 的數。質數的 \(1\) 次方已經在前面列舉質數的地方算過了因此在 \(e = 1\) 時不再計算。

合起來有

\[s(n, j) = q(n) - \sum\limits_^ f(p_i) + \sum\limits_ \sum\limits_^ f(p_k^e)[s(\frac, k) + (e>1)]

\]最終求的答案是 \(s(n, 0) + f(1)\), 還要加上 \(f(1)\) 因為 \(s\) 函式不會計算到 \(1\)。

我們現在的目標是計算 \(q(n)\)。

完全積性函式 \(f'\) 在質數處取值與 \(f\) 相同。

考慮一步一步把合數的貢獻給消除。設乙個函式 \(g\),滿足 \(g(n,j)=\sum\limits_^n f'(i)(i \in prime | \min\limits_ p > p_j)\)。

考慮計算 \(g(n, j-1) - g(n, j)\)。

當 \(p_j^2 > n\) 時, \(g(n, j - 1)\) 顯然沒有多餘貢獻, 即 \(g(n, j) = g(n, j-1)\)。

否則如果數 \(x\) 在 \(g(n, j - 1)\) 中有多餘貢獻的數,\(x\) 一定有質因子 \(p_j\)。可以先把有質因子 \(p_j\) 的數都除以 \(p_j\) 。

這些數剩下的所有質因子都大於等於 \(p_j\),因此是 \(g(\frac, j - 1) - \sum\limits_^f'(p_i)\) (注意 \(g(\frac, j-1)\) 會多算一些質數,因此後面需要減 \(\sum\limits_^f'(p_i)\))。

因此得出狀態轉移方程:

\[g(n, j)=\beging(n, j-1) (p_j^2 > n)\\g(n, j-1) - f'(p_j)(g(\frac, j-1) - \sum\limits_^f'(p_i))(p_j^2 \le n)\end

\]這樣可以方便地計算 \(q(n) = g(n, |p|)\) 。

\(g\) 函式需要的地方都是 \(g(\left\lfloor\frac\right\rfloor, ...)\) 的形式。

眾所周知 \(\left\lfloor\frac\right\rfloor\) 的取值只有 \(2\sqrt\) 種情況。讓 \(id1_k\) 記錄 \(k\le\sqrt n\), \(id2_k\) 記錄 \(\frac \le \sqrt n\),可以只列舉這 \(2\sqrt n\) 種情況。

在處理質數處的完全積性函式時, \(p^k(p^k-1)\) 可以用 \(p^\) 減 \(p^k\) 表示(儘管在合數的情況答案變了,但是在質數處沒變,因此答案不變)。

於是就可以為 \(g\) 函式賦初值(\(g(n, 0) = \sum\limits_^ f'(i)\))。

總結一下,min_25 篩能用的前提:質數處的 \(f(p)\) 值是關於 \(p\) 的多項式,質數次方處的 \(f(p^e)\) 值可以快速計算。

#include#define l(i, j, k) for(int i = j, i##e = k; i <= i##e; i++)

#define r(i, j, k) for(int i = j, i##e = k; i >= i##e; i--)

#define ll long long

#define ull unsigned long long

#define db double

#define pii pair#define mkp make_pair

#define ll long long

using namespace std;

const int n = 2e5 + 7;

const int mod = 1e9 + 7;

bool prime[n];

int tot;

ll p[n], n, sq, w[n], m, sum1[n], sum2[n], g1[n], g2[n], id1[n], id2[n];

// id1 id2 如文中所示 w[k] 為第 k 個需要處理的數

// 文中的 g 為 g2 - g1, g1 : f'(k) = k, g2: f'(k) = k ^ 2

// sum1 : 質數字首和 ; sum2: 質數平方字首和

void xxs()

} l(i, 1, tot)

}ll getid(ll x)

ll f1(ll x)

ll f2(ll x)

ll s(ll x, int j)

int main()

l(i, 1, tot)

} printf("%lld\n", (s(n, 0) + 1) % mod);

return 0;

}

祝大家學習愉快!

Min 25 篩學習筆記

資料和 出處 資料2資料3 打死我也不承認參考了yyb的 min 25 篩可以幹嘛?下文中未特殊說明 p 均指質數集合,p i 或 p 指某個具體質數。求一類積性函式 f x 的字首和,需要滿足 f p 可以寫成多項式的形式,或者操作一下可以寫成多項式 如例題 且 f p k 能快速求出。講真學這個...

Min 25 篩 學習筆記

埃氏篩法 整除分塊 這裡有提到 1.問題模型 2.min 25 篩 3.模板題以及模板 有乙個積性函式 f 對於所有質數 p f p 是關於 p 的多項式,f p k 非常容易計算 不一定是關於 p 的多項式 求 sum f i n leq 10 1s 設集合 p 表示素數集合。設 g sum f ...

Min 25篩 學習筆記

這兒只是乙個簡單說明 概括 總結。原理見這 min 25篩用來求積性函式字首和。範圍一般是 10 要求所求積性函式在 f i 已知時,f p times i p in primes,i times p in 1,n 能快速計算。首先計算 g n,j sum if i quad i是質數 或 i的最小...