1.自然语言描述
质数:除了1和它本身之外没有因数的数。
试除法判定质数:根据质数定义,判断这个数能不能被1和它本身之外的数整除;若能则说明这个数不是质数,若不能则这个数是质数。
分解质因数:任意一个合数都可以分解为若干个质数幂相乘的形式。
质数筛:得到2~n之间所有的质数,用一个标记数组st[i]判断i是否是质数。
2.代码描述
题目:Acwing.866 试除法判定质数题目链接
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int main(void)
{
int n;
cin>>n;
while(n--){
int x;
cin>>x;
if(x==1){//1不是质数
cout<<"No"<<endl;
continue;
}
bool flag=true;
for(int i=2;i<=x/i;i++)//从2枚举到x的最大因子sqrt(n),但因为sqrt(n)执行耗时大,这里换了一种耗时小的写法
if(x%i==0){//发现了非1和x本身的因子,x不是质数
flag=false;
break;
}
if(flag)
cout<<"Yes"<<endl;
else
cout<<"No"<<endl;
}
return 0;
}
题目:Acwing.867 分解质因数题目链接
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int main(void)
{
int n;
cin>>n;
while(n--){
int x;
cin>>x;
for(int i=2;i<=x/i;i++){//定理:任何一个合数都可以分解为若干个质数幂相乘的形式。
if(x%i==0){ //因此,每次发现质因子并让x除以这些质因子若干次幂使x去除掉这个质因子
//之后枚举到的符合x%i==0条件的一定是另一个质因子。
int s=0;
while(x%i==0){//去掉x中质数i的幂
x/=i;
s++;
}
cout<<i<<' '<<s<<endl;//输出质数的底数和指数部分
}
}
if(x>1)
cout<<x<<' '<<1<<endl;
cout<<endl;
}
return 0;
}
题目:Acwing.868 筛质数题目链接
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXN=1e6+10;
int n,primes[MAXN],cnt;
bool st[MAXN];
//朴素质数筛:如果i是质数则记录,并将当前i的所有2~n之间的倍数筛除
// void calc1()
// {
// for(int i=2;i<=n;i++){
// if(!st[i])
// primes[cnt++]=i;
// for(int j=2*i;j<=n;j+=i)
// st[j]=true;
// }
// }
//埃式筛法:不需要筛除合数的倍数,只筛掉质数的所有2~n之间的倍数
// void calc2()
// {
// for(int i=2;i<=n;i++){
// if(!st[i]){
// primes[cnt++]=i;
// for(int j=2*i;j<=n;j+=i)
// st[j]=true;
// }
// }
// }
//线性筛:由于是从小到大枚举,得到的质数也是从小到大的,所以每个数可以被它的最小质因子筛去
void calc3()
{
for(int i=2;i<=n;i++){
if(!st[i])
primes[cnt++]=i;
for(int j=0;primes[j]<=n/i;j++){//由于是从小到大筛取质数的,每一个数一定会被它的最小质因子筛去
st[primes[j]*i]=true;//primes[j]小于i的所有质因子,同时primes[j]*i的最小质因子为primes[j]
if(i%primes[j]==0)//i的最小质因子为primes[j],同时primes[j]*i的最小质因子为primes[j](前一个语句一定筛过了)
break;//让所有的非质数只被筛一次,故名线性筛
}
}
}
int main(void)
{
cin>>n;
//calc1();
//calc2();
calc3();
cout<<cnt<<endl;
return 0;
}