min_25筛学习小记

min_25筛是洲阁筛的简化版,虽然我并不会洲阁筛。

min_25筛可以筛一些特殊积性函数的前缀和,有些不是积性函数也可以筛,比如说最大真因子。

同杜教筛一样,同时筛出了所有 ⌊ n i ⌋ \lfloor {n \over i} \rfloor in的前缀和。

至于min_25能筛的积性函数有哪些要求,在博客后面会讨论

所有时间复杂度证明见朱大佬2018国家预备队论文。

筛的本质:

1 − n 1-n 1n内的所有数的最小质因子都会不大于 n \sqrt n n ,同欧拉筛法,我们就是在枚举到一个数的最小质因子的时去统计到它。

Step 1:

洲阁筛的第一步就是求出n以内所有质数p的 ∑ f ( p ) \sum f(p) f(p)

f ( p ) f(p) f(p)一般是和p有关的多项式,如果 f ( p ) f(p) f(p)能够拆成若干个完全积性函数的式子,那么这个 f f f就是可以筛的。

这个可能有点难理解,可以看下面的式子来得到。

以筛质数个数为例,显然有 f ( p ) = 1 f(p)=1 f(p)=1

预处理 n \sqrt n n 以内的质数,第j大的质数设为 p j p_j pj

g ( n , j ) g(n,j) g(n,j)表示 2 − n 2-n 2n的数中,要么是质数,要么最小质因子大于 p j p_j pj,把合法的数当作质数算的答案。

解释一下何为当作质数:
对于一个质数 p p p f ( p ) f(p) f(p)一般是和 p p p有关的式子,对于一个 x x x,我们不考虑它是不是质数,而是直接像质数那样算出和 x x x有关的值。

g ( n , j ) = { g ( n , j − 1 ) p j 2 &gt; n g ( n , j − 1 ) − f ( p j ) [ g ( n p j , j − 1 ) − ∑ i = 1 j − 1 f ( p i ) ] p j 2 &lt; = n g(n,j)= \begin{cases} g(n,j-1)&amp;p_j^2&gt;n\\ g(n,j-1)-f(p_j)[g(\frac{n}{p_j},j-1)-\sum_{i=1}^{j-1}f(p_i)]&amp;p_j^2&lt;= n \end{cases} g(n,j)={g(n,j1)g(n,j1)f(pj)[g(pjn,j1)i=1j1f(pi)]pj2>npj2<=n

第二条式子中,因为 g g g的定义含有质数,而我们的目的是使 p j p_j pj成为最小质因子,所以要减掉它们。

由于用到的n一定是 ⌊ n i ⌋ \lfloor {n \over i} \rfloor in,所以只用记录 n \sqrt n n 个值。
初值:
在求质数个数中, g ( n , 0 ) = n − 1 g(n,0)=n-1 g(n,0)=n1,其它题中,可能是和n有关的奇奇怪怪的东西。

题目:LOJ#6235. 区间素数个数

for(ll i = 1, j; i <= n; i = j + 1) {
	j = n / (n / i); w[++ m] = n / i;
	if(w[m] <= sqr) id1[w[m]] = m; else id2[n / w[m]] = m;
	g[m] = w[m] - 1;
}
fo(j, 1, p[0]) for(int i = 1; i <= m && p[j] * p[j] <= w[i]; i ++) {
	int k = (w[i] / p[j] <= sqr) ? id1[w[i] / p[j]] : id2[n / (w[i] / p[j])];
	g[i] += - g[k] + j - 1;
}

显然 g g g只有 g ( n , p 0 ) g(n,p0) g(n,p0)才有用,p0为 n \sqrt n n 以内的质数个数,为了方便,后面用 g ( n ) g(n) g(n)表示 g ( n , p 0 ) g(n,p0) g(n,p0)

以上写法复杂度为 O ( n 3 4 l o g   n ) O({n^{3 \over 4} \over log~n}) O(log nn43)

Step 2:

递归版:

知道了 g g g就可以求答案了。

s ( n , j ) s(n,j) s(n,j)表示2-n中的所有数,最小质因子大于等于 p j p_j pj的所有数x的 ∑ f ( x ) \sum f(x) f(x)

s ( n , j ) = g ( n ) − ∑ i = 1 j − 1 f ( p i ) + ∑ k = j p 0 ∑ e ∣ e &gt; = 1 和 p k e + 1 &lt; = n   f ( p k e ) ∗ s ( n / p k e , k + 1 ) + f ( p k e + 1 ) s(n,j)=g(n)-\sum_{i=1}^{j-1}f(p_i)+\sum_{k=j}^{p0} \sum_{e|e&gt;=1和p_k^{e+1}&lt;=n}~f(p_k^e)*s(n/p_k^e,k+1)+f(p_k^{e+1}) s(n,j)=g(n)i=1j1f(pi)+k=jp0ee>=1pke+1<=n f(pke)s(n/pke,k+1)+f(pke+1)

不用hash,直接强行递归复杂度为 O ( n 3 4 l o g   n ) O({n^{3 \over 4} \over log~n}) O(log nn43)

题目:LOJ#6053. 简单的函数

#include<cmath>
#include<cstdio>
#define ll long long
#define fo(i, x, y) for(int i = x; i <= y; i ++)
using namespace std;

const int mo = 1e9 + 7, ni2 = 5e8 + 4;

const int N = 2e5 + 5;

ll n, w[N];
int m, sqr, i1[N], i2[N];
int bz[N], p[N], sp[N];
int h[N], g[N];

void sieve(int n) {
	fo(i, 2, n)	 {
		if(!bz[i]) p[++ p[0]] = i, sp[p[0]] = (sp[p[0] - 1] + i) % mo;
		for(int j = 1; i * p[j] <= n; j ++) {
			bz[i * p[j]] = 1;
			if(i % p[j] == 0) break;
		}
	}
}

int dg(ll x, int y) {
	if(x <= 1 || p[y] > x) return 0;
	int k = x <= sqr ? i1[x] : i2[n / x];
	int s = ((ll) g[k] - h[k] - (sp[y - 1] - (y - 1)) + mo + mo) % mo;
	if(y == 1) s = (s + 2) % mo;
	for(int i = y; i <= p[0] && (ll) p[i] * p[i] <= x; i ++) {
		ll p1 = p[i], p2 = (ll) p[i] * p[i];
		for(int e = 1; p2 <= x; e ++, p1 = p2, p2 *= p[i])
			s = (s + (ll) dg(x / p1, i + 1) * (p[i] ^ e) % mo + (p[i] ^ (e + 1))) % mo;
	}
	return s;
}

int main() {
	scanf("%lld", &n);
	sqr = sqrt(n); sieve(sqr);
	for(ll i = 1, j; i <= n; i = j + 1) {
		j = n / (n / i); w[++ m] = n / i;
		if(w[m] <= sqr) i1[w[m]] = m; else i2[n / w[m]] = m;
		h[m] = (w[m] - 1) % mo;
		g[m] = (w[m] - 1) % mo * ((w[m] + 2) % mo) % mo * ni2 % mo;
	}
	fo(j, 1, p[0]) for(int i = 1; i <= m && (ll) p[j] * p[j] <= w[i]; i ++) {
		int k = (w[i] / p[j] <= sqr) ? i1[w[i] / p[j]] : i2[n / (w[i] / p[j])];
		g[i] = ((ll) g[i] - (ll) p[j] * (g[k] - sp[j - 1]) % mo + mo) % mo;
		h[i] = (h[i] - h[k] + (j - 1) + mo) % mo;
	}
	printf("%d\n", (dg(n, 1) + 1) % mo);
}
递推版:

更改 s s s的定义,类似于之前的 g g g
s ( n , j ) s(n,j) s(n,j)表示2-n的数中,要么是质数,要么最小质因子大于等于 p j p_j pj的数 x x x ∑ f ( x ) \sum f(x) f(x)
s ( n , j ) = s ( n , j + 1 ) + ∑ e ∣ e &gt; = 1 和 p j e + 1 &lt; = n   f ( p j e ) ∗ s ( n / p j e ) + f ( p j e + 1 ) s(n,j)=s(n,j+1)+\sum_{e|e&gt;=1和p_j^{e+1}&lt;=n}~f(p_j^e)*s(n/p_j^e)+f(p_j^{e+1}) s(n,j)=s(n,j+1)+ee>=1pje+1<=n f(pje)s(n/pje)+f(pje+1)
初值 s ( n , p 0 + 1 ) = g ( n ) s(n,p0+1)=g(n) s(n,p0+1)=g(n),写法类似于g,就是先枚举j,然后再转移。

对比:

根据LL实测,递归版在求一个的时候会比递推版快,因为有些状态走不到。

但是如果对于所有的 ⌊ n i ⌋ \lfloor {n \over i} \rfloor in都要求前缀和,就只能用递推版了。

### 原理概述 #### 是一种高效的法,用于计算数论函数的前缀和。其主要思想是通过分段处理和利用数论函数的性质来减少不必要的计算。的时间复杂度通常被认为是亚线性的,适用于大规模数据的处理。的核心在于将区间分成多个小段,并利用已知的数论函数值来加速计算过程。 #### Min_25 Min_25是一种更为高效的法,特别适用于计算积性函数的前缀和。Min_25的时间复杂度为 $\Theta(\frac{n^{\frac{3}{4}}}{\log_2 n})$,在 $n \leq 1e13$ 的情况下,可以通过一些优化技巧达到更好的性能。Min_25的基本思想是利用完全积性函数的性质,通过法去除合数的影响,从而得到质数的贡献。具体来说,Min_25通过构造一个完全积性函数来简化法过程,并利用递归的方法计算出所需的前缀和 [^1]。 ### 应用场景 #### 的应用 主要用于处理大规模的数据集,特别是在数论中计算积性函数的前缀和。例如,在计算莫比乌斯函数的前缀和时,可以显著减少计算时间。 #### Min_25的应用 Min_25在数论中有着广泛的应用,特别是在计算积性函数的前缀和时。例如,Min_25可以用于快速计算出 $f(x)$ 的前缀和,其中 $f(x)$ 是一个积性函数。Min_25的高效性使其在处理大规模数据时表现出色 [^1]。 ### 算法实现 #### Min_25的实现步骤 1. **初始化**:首先初始化所有质数的贡献。 2. **法过程**:利用完全积性函数的性质,逐步去合数的贡献。 3. **递归计算**:通过递归的方式计算出每个区间的贡献。 具体的实现代码如下: ```python def min_25_sieve(n): # 初始化质数列表 primes = [] # 初始化法数组 g = [0] * (n + 1) # 初始化质数计数数组 prime_count = [0] * (n + 1) # 初始化最小质因子数组 min_prime = [0] * (n + 1) # 法过程 for i in range(2, n + 1): if min_prime[i] == 0: primes.append(i) min_prime[i] = i for j in range(len(primes)): if primes[j] > min_prime[i] or i * primes[j] > n: break min_prime[i * primes[j]] = primes[j] # 计算质数的贡献 for i in range(1, n + 1): g[i] = i # 假设f(x) = x # 去合数的贡献 for p in primes: for i in range(n // p, 0, -1): g[i] -= g[i // p] return g[n] ``` ### 复杂度分析 #### 的复杂度 的时间复杂度通常被认为是亚线性的,具体复杂度取决于具体的实现和优化技巧。 #### Min_25的复杂度 Min_25的时间复杂度为 $\Theta(\frac{n^{\frac{3}{4}}}{\log_2 n})$,在 $n \leq 1e13$ 的情况下,可以通过一些优化技巧达到更好的性能 [^2]。 ### 总结 Min_25都是高效的法,适用于计算数论函数的前缀和。Min_25在处理大规模数据时表现出色,其复杂度分析表明其在实际应用中具有较高的效率 [^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值