模板
在本文中用 \(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的最小...