质数筛法

1. 埃拉托斯特尼筛法

从小到大枚举每一个数 x,考虑标记每一个合数,如果 x 没被标记,那么它就是质数,所以 x×i 就是合数,将它们标记,由于小于 x2x 的倍数之前已经筛过了,所以从 x2 开始。最后没被标记的就是质数,复杂度 O(nlognlogn)

这种筛法可以进行优化,例如枚举到 n,只筛奇数,bitset 优化等等,甚至可以快过线性筛法。

bitset<N> not_prime;
not_prime[1]=1;
for(int i=2;i*i<=n;i++)
{
   if(not_prime[i]==0)
	{
		for(int j=i*i;j<=n;j+=i)
		{
			not_prime[j]=1;
		}
	}
}
For(i,1,n)
{
	if(!not_prime[i]) prime[++cnt]=i;
}

2. 欧拉筛

埃氏筛法会将一个合数重复多次标记。如果能让每个合数都只被标记一次,那么时间复杂度就可以降到 O(n) 了。

考虑让每一个合数只被其最小质因子标记。还是从小到大枚举每一个数 i,标记每一个合数,维护一个质数的序列 p,如果 i 没被标记,那么将它加入这个序列,接下来遍历这个序列(无论 i 是不是一个质数),标记 i×pj 为合数,如果 ipj 的倍数,那么就可以直接 break 了,这是由于:

如果不 break 的话,那么 i×pj+1 就会被 pj+1 标记,而 pji,所以 pj 也是 i×pj+1 的一个质因数,由于序列 p 是递增的,所以 pj<pj+1,所以 pj+1 不是 i×pj+1 的最小质因子,违背了每一个合数只被其最小质因子标记的原则,所以需要 break

for(int i=1;i<=n;i++)
{
	if(!notprime[i])
	{
		prime[++cnt]=i;
	}
	for(int j=1;j<=cnt&&(long long)i*prime[j]<n;j++)
	{
		notprime[i*prime[j]]=1;
		if(i%prime[j]==0)
		{
			break;
		}
	}
} 
posted @   zhuluoan  阅读(90)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示