首页 > 其他 > 详细

常见积性函数线筛

时间:2020-04-20 23:44:42      阅读:78      评论:0      收藏:0      [点我收藏+]

\(OK\),那这就是我的第一篇博客了\(QwQ\)

众所周知这个 \(lyy\) 是个 \(big\ \ colorful\ \ pen\) ,他的数学严重限制了他的信竞,所以适当地做做笔记或总结对这个菜得没救了的人也是有点帮助的。


线性筛素数

万恶之源,比埃氏筛更优的线性筛,线性体现在每个数会被它最小的质因子筛掉,最小的质因子显然只有一个,每个数只会被访问一次,严格的线性复杂度。

一个数被访问是由枚举“除去它最小的质因子后的值 \(i\) ”,再乘上“最小质因子 \(prime[j]\)(以下简写为\(p[j]\))”实现的。例如 \(8\) 是在 \(i=4,p[j]=2\) 时被访问的,\(12\) 是在 \(i=6,p[j]=2\) 时被访问的,\(9\)\(i=3,p[j]=3\) (可以看到需要先把 \(i\) 加入质数中再枚举质数)。若当前的 \(i\) 没有被访问,说明 \(i\) 最小的质因子是它本身,显然 \(i\) 就是个质数。

为了保证当前质因子是乘积的最小质因子,当 \(i\%p[j]==0\) 时停止对 \(j\) 的枚举,因为此时 \(i\) 中保证有质因子 \(p[j]\),当 \(p[j]\) 继续增大时,\(i\)\(p[j]\) 乘积的最小质因子不会再是 \(p[j]\),而是i中的最小质因子。

for(int i=2; i<=n; i++) {
	if(!vis[i]) p[++cnt] = i;
	for(int j=1; j<=cnt && i*p[j]<=n; j++) {
		vis[ i*p[j] ] = 1;
		if(i%p[j]==0) break;    //与埃氏筛唯一的区别
	}
}

有了线性筛,遇到1e7的毒瘤题也不用慌了。


积性函数

积性函数是指当 \(a\)\(b\) 互质时满足 \(f(ab)=f(a)*f(b)\) 的函数。常见的像欧拉函数 \(\phi\) ,约数个数 \(d\), 约数和 \(\sigma\),莫比乌斯函数 \(\mu\)。所有的积性函数都能线筛(大概)。

我们在线性筛时,每个数是由 \(i\)\(p[j]\) 乘起来得到的。
\(i\%p[j]!=0\),因为 \(p[j]\) 是质数所以 \(i\)\(p[j]\) 互质,\(f( i*p[j] )=f(i)*f(p[j])\)
\(i\%p[j]=0\),我们一般需要考虑这个数中最小的质因子 \(p[j]\) 的出现次数对它函数值的影响,一般需要另设一个函数 \(g\) 来记录最小质因子的出现次数,当 \(i\%p[j]=0\) 时,\(g[i*p[j]]=g[i]+1\),而 \(f\) 值就要具体情况具体分析了。

欧拉函数 \(\phi\) 线筛

欧拉函数 \(\phi\),表示比 \(x\) 小的与 \(x\) 互质的数的个数,求单个的话是 \(sqrt\) 复杂度的。

\(x=p_1^{k1}*p_2^{k2}*p_3^{k3}...p_n^{kn}\),则\(\phi(x)=x\prod\limits_{i=1}^n\dfrac {p_i-1} {p_i}\)。这个很好证,就是考虑每个质因子对 \(\phi\) 值的贡献。

\(\phi\) 是积性函数也就显然了,因为互质的两个数没有相同的 \(p\),两个数的质因子贡献互不影响。

所以当 \(i\%p[j]!=0\) 时,\(\phi(i*p[j])=\phi(i)*\phi(j)=\phi(i)*(p[j]-1)\)
\(i\%p[j]=0\) 时,由于 \(p[j]\) 已经在 \(i\) 中出现,所以乘上 \(p[j]\) 不会对 \(\phi\) 造成影响,\(\phi(i*p[j])=\phi(i)*p[j]\)

for(int i=2; i<=n; i++) {
	if(!vis[i]) {
		p[++cnt] = i;
		phi[i] = i-1;
	}
	for(int j=1; j<=cnt && i*p[j]<=n; j++) {
		vis[ i*p[j] ] = 1;
		if(i%p[j]==0) {
			phi[ i*p[j] ] = phi[i] * p[j];
			break;
		}
		phi[ i*p[j] ] = phi[i] * (p[j]-1);
	}
}

约数个数 \(d\) 线筛

一个显然的结论:若\(x=p_1^{k1}*p_2^{k2}*p_3^{k3}...p_n^{kn}\),则\(d(x)=\prod\limits_{i=1}^n(k_i+1)\)。若x与y互质,那么x与y没有相同的质因子,显然\(d(xy)=d(x)*d(y)\),所以 \(d\) 是个积性函数。

考虑同样的线筛方式,当 \(i\%p[j]!=0\) 时,\(d(i*p[j])=d(i)*d(p[j])=d(i)*2\)
\(i\%p[j]=0\) 时,相当于 \(p[j]\) 的指数从 \(k_j\) 变成了 \(k_j+1\),辣么它的d就从一大坨乘上 \(k_j+1\) 变成一大坨乘上 \(k_j+2\) ,所以有必要开一个 \(g\) 记录最小质因子出现次数,\(g[ i*p[j] ]=g[i]+1,d[i*p[j]]=d[i]/(g[i]+1)*(g[i]+2)\)。记得当 \(i\) 是质数时,\(d[i]=2,g[i]=1\)

d[1] = 1;
for(int i=2; i<=n; i++) {
    if(!vis[i]) {
        p[++cnt] = i;
        d[i] = 2; g[i] = 1;
    }
    for(int j=1; j<=cnt && i*p[j]<=n; j++) {
        vis[ i*p[j] ] = 1;
        if(i%p[j]==0) {
            d[ i*p[j] ] = d[i] / (g[i]+1) * (g[i]+2);
            g[ i*p[j] ] = g[i] + 1;
            break;
        }
        d[ i*p[j] ] = d[i] * 2;
        g[ i*p[j] ] = 1;
    }
}

约数和 \(\sigma\) 线筛

前方施工中。。。

常见积性函数线筛

原文:https://www.cnblogs.com/clever-sheep/p/12741425.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!