cqbz笔记补全计划1
筛质数
在OI赛中,我们经常需要筛质数的题,这个时候选择什么筛法之冠重要(避免TLE)
法1 暴力(O(sqrt(n)))
bool pzs(int n)//判断n为合数或质数,1为合数,0为质数
{
if (n<2)retrun 1;
for (int i=2;i*i<=n;i++)if(n%i==0)return 1;
return 0;
}
法2 埃筛
该筛法的核心思想是此数若未被筛,则为质数,筛为合数,筛去此数与所有以找到质数之几。
代码
#include<bits/stdc++.h>
using namespace std;
bool pzs[1000005];
int zs[1000005],n;
int main ( )
{
cin>>n;
for (int i=2;i<=n;i++)
{
if (pzs[i]==0)
{
zs[0]++;
zs[zs[0]]=i;
}
for (int j=1;j<=zs[0];j++)pzs[zs[j]*i]=1;
}
for (int i=1;i<=zs[0];i++)cout<<zs[i]<<" ";
}
该程序是求1~n之间的质数,但是,不是最好方法,如43,62,
12被筛了两次。
法3 欧拉筛(线性筛)
该筛法是在埃筛的基础上加以改进,总所周知,任何一个数都只有一个最小质因数,所以,只用最小质因数筛。
代码
#include<bits/stdc++.h>
using namespace std;
bool pzs[1000005];
int zs[1000005],n;
int main ( )
{
cin>>n;
for (int i=2;i<=n;i++)
{
if (pzs[i]==0)
{
zs[0]++;
zs[zs[0]]=i;
}
for (int j=1;j<=zs[0];j++)
{
pzs[zs[j]*i]=1;
//如果i含有第j大的质因数分子,则不必枚举,因为该质数以筛去
if (i%zs[j]==0)break;//有人认为,该句应该在16行之前,举个反例:2*2=4
}
}
for (int i=1;i<=zs[0];i++)cout<<zs[i]<<" ";
}
完
并没有完:
实列:
1.某位鸣叫FXL特殊的质数肋骨是使用欧拉筛,然后TLE。我暴力分解BFS,AC。这就是为什么选择对很重要。