min_25筛学习笔记

参考博客

zsy

xuyixuan

litble

前置

m i n 2 5 min_25 min25就是一种能在低于线性复杂度求积性函数 f ( x ) f(x) f(x)前缀和的筛法

复杂度大概为 O ( n 3 4 l o g n ) O(\frac{n^{\frac 3 4}}{log_n}) O(lognn43)(不会证,不过朱老大论文里有证明(看不懂))

要求 f ( x ) f(x) f(x)是一个积性函数且可以看做若干完全积性函数的组合(或者某些特殊的使得 f ( p k ) f(p^k) f(pk)可以处理的),而且对于素数 p p p f ( p ) f(p) f(p) f ( p k ) f(p^k) f(pk)可以快速得到

g g g

P P P表示素数集合, M i n k Min_k Mink表示 k k k的最小质因子

p r i pr_i pri表示从小到大第 i i i个素数

首先考虑求出 ∑ i = 1 n [ i ∈ P ] f ( i ) \sum_{i=1}^{n}[i\in P] f(i) i=1n[iP]f(i)

定义 g ( n , i ) = ∑ j = 1 n [ j ∈ P o r M i n j > p r i ] f ( j ) g(n,i)=\sum_{j=1}^{n}[j\in P{or}Min_j>pr_i] f(j) g(n,i)=j=1n[jPorMinj>pri]f(j)

仔细瞪一下这个函数

我们发现从 g ( n , i − 1 ) g(n,i-1) g(n,i1) g ( n , i ) g(n,i) g(n,i)

我们就相当于做埃氏筛的过程,用 p r i pr_i pri [ 1 , n ] [1,n] [1,n]所有还没有被筛去的 p r i pr_i pri的倍数筛去

实际上 g ( n , i ) g(n,i) g(n,i)就是对 [ 1 , n ] [1,n] [1,n]用前 i i i个素数做一次埃氏筛后剩下的数 f f f之和

现在考虑怎么从 g ( n , i − 1 ) g(n,i-1) g(n,i1)推到 g ( n , i ) g(n,i) g(n,i)

首先如果 p r i 2 > n pr_{i}^2> n pri2>n那显然不会有筛去任何数

否则考虑哪些数被删去了

一定是含质因子 p i p_i pi,而且除去 p i p_i pi后最小质因子一定大于 p i p_i pi
也就是减去 f ( p i ) × g ( n p i , i − 1 ) f(p_i)\times g(\frac n {p_i},i-1) f(pi)×g(pin,i1)

又由于我们把 p r 1 pr_1 pr1~ p r i − 1 pr_{i-1} pri1这些素数的 f f f值减去了,所以要再加一个 ∑ j = 1 i − 1 f ( p j ) \sum_{j=1}^{i-1}f(p_j) j=1i1f(pj)

所以
g ( n , i ) = { g ( n , i − 1 ) n < p i 2 g ( n , i − 1 ) − f ( p i ) × [ g ( n p i , i − 1 ) − ∑ j = 1 i − 1 f ( p j ) ] p i 2 ≤ n g ( n , i ) = n i = 0 g(n,i)= \begin{cases} g(n,i-1) && n<p_i^2\\ g(n,i-1)-f(p_i)\times[g(\frac n{p_i},i-1)-\sum_{j=1}^{i-1}f(p_j)] && p_i^2\le n\\ g(n,i)=n && i=0 \end{cases} g(n,i)=g(n,i1)g(n,i1)f(pi)×[g(pin,i1)j=1i1f(pj)]g(n,i)=nn<pi2pi2ni=0

由于最后实际要求的是 g ( n , ∣ P ∣ ) g(n,|P|) g(n,P),我们只需要开一维就可以了,第二维可以类似滚动数组滚掉

又由于大于 n \sqrt n n 的质因子只有一个

所以我们可以记 f 1 [ i ] f1[i] f1[i]表示 g ( i , j ) g(i,j) g(i,j) f 2 [ i ] f2[i] f2[i]表示 g ( n i , j ) g(\frac n i,j) g(in,j)

这样空间复杂度只有 O ( n ) O(\sqrt n) O(n )

代码:当 f ( p ) = 1 f(p)=1 f(p)=1即求素数个数时
代码实现比较精细
可以证明这样复杂度是 O ( n 3 4 l o g n ) O(\frac{n^{\frac 3 4}}{log_n}) O(lognn43)

int lim=sqrt(n);
for(int i=1;i<=lim;i++)f1[i]=i-1,f2[i]=n/i-1;
for(int p=2;p<=lim;p++){
	if(f1[p]==f1[p-1])continue;
	for(int i=1;i<=lim/p;i++)f2[i]-=f2[i*p]-f1[p-1];
	for(int i=lim/p+1;1ll*i*p*p<=n&&i<=lim;i++)f2[i]-=f1[n/i/p]-f1[p-1];
	for(int i=lim;i>=1ll*p*p;i--)f1[i]-=f1[i/p]-f1[p-1];
}
return f2[1];

但是会跑的很慢
你找一照发现问题很简单
卡一下数组枚举和除法以及一些常用变量就会快 5 、 6 5、6 56

lim=sqrt(n);
for(i=1;i<=lim;++i)f1[i]=i-1,f2[i]=n/i-1,inv[i]=1.0/i;
for(p=2;p<=lim;++p){
	if(f1[p]==f1[p-1])continue;
	x0=f1[p-1],w1=lim/p,w2=min(lim,(n/p/p)),dd=n/p;
	for(i=1;i<=w1;++i)f2[i]+=x0-f2[i*p];
	for(i=lim/p+1;i<=w2;++i)f2[i]+=x0-f1[(int)(inv[i]*dd+1e-7)];
	for(i=lim;i>=1ll*p*p;--i)f1[i]+=x0-f1[(int)(inv[p]*i+1e-7)];
}
return f2[1];

可以注意到由于是直接把 f ( p ) f(p) f(p)拆出去,所以必须要 f f f为完全积性函数或者是质因子个数这种特殊的函数,如果是积性且为若干完全积性函数线性组合可以分开维护最后组合起来

S S S

现在我们已经求出了 ∑ i = 1 n [ i ∈ P ] f ( i ) \sum_{i=1}^{n}[i\in P] f(i) i=1n[iP]f(i)

考虑如何计算合数的答案

S ( n , i ) = ∑ j = 1 n [ M i n j ≥ p r i ] f ( j ) S(n,i)=\sum_{j=1}^n [Min_j\geq pr_i] f(j) S(n,i)=j=1n[Minjpri]f(j)

即满足所有质因子大于等于 p i p_i pi的数的 f f f之和

那么显然 ∑ i = 1 n f ( i ) = S ( n , 1 ) + f ( 1 ) \sum_{i=1}^{n} f(i)=S(n,1)+f(1) i=1nf(i)=S(n,1)+f(1)
考虑如何类似的递推

首先素数的答案已经算出来了
显然的是 g ( n , ∣ P ∣ ) − ∑ j = 1 i − 1 f ( p r j ) g(n,|P|)-\sum_{j=1}^{i-1}f(pr_j) g(n,P)j=1i1f(prj)(因为 S S S要求 M i n j ≥ p r i Min_j\ge pr_i Minjpri)

考虑枚举合数的最小质因子和次数,直接算就是了

S ( n , i ) = g ( n , ∣ P ∣ ) − ∑ j = 1 i − 1 f ( p r j ) + ∑ j = i p r j 2 ≤ n ∑ x s = 1 p r j x s + 1 ≤ n S ( n p r j x s , j + 1 ) × f ( p r j x s ) + f ( p r j x s + 1 ) S(n,i)=g(n,|P|)-\sum_{j=1}^{i-1}f(pr_j)+\sum_{j=i}^{pr_j^2\le n}\sum_{xs=1}^{pr_j^{xs+1}\le n}S(\frac{n}{pr_j^{xs}},j+1)\times f(pr_j^{xs})+f(pr_j^{xs+1}) S(n,i)=g(n,P)j=1i1f(prj)+j=iprj2nxs=1prjxs+1nS(prjxsn,j+1)×f(prjxs)+f(prjxs+1)

关于这部分的复杂度:
论文里说的是 n 3 4 l o g \frac{n^{\frac 3 4}}{log} logn43
好像基于的关于质数的分析在 1 0 12 10^{12} 1012内是满足的
更大范围内应该说是 n 1 − ϵ n^{1-\epsilon} n1ϵ
不过更大范围也跑不过去的

然后就没了
代码看例题里的就可以了

例题:

L O J 6235 LOJ6235 LOJ6235

L O J 6202 LOJ6202 LOJ6202

L O J 6053 LOJ6053 LOJ6053

U O J 188 UOJ188 UOJ188

B Z O J 5244 BZOJ5244 BZOJ5244

S P O J − D I V C N T K SPOJ-DIVCNTK SPOJDIVCNTK

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值