一.素数的概念
素数是指只能被1和自身整除的正整数。换句话说,如果一个数除了1和它本身以外没有其他因数,那么它就是素数。例如,2、3、5、7、11、13等都是素数,而4、6、8、9、10等就不是素数。素数在数学和计算机科学中都有广泛的应用。
0和1既不是素数也不是合数!
二.根据概念写出的暴力算法(O(n))
思路:既然只能被1和本身整除的是素数,那不妨枚举(1,n)直接的数,若能整除,则不是素数!
代码:
#include<bits/stdc++.h> // 引入头文件,包含了所有标准库函数的声明
using namespace std; // 使用标准命名空间
bool is_prime(int n){ // 定义一个函数,判断一个数是否为素数
for(int i=2;i<n;i++){ // 从2开始遍历到n-1
if(n%i==0) return false; // 如果n能被i整除,说明n不是素数,返回false
}
return true; // 如果n不能被任何一个i整除,说明n是素数,返回true
}
int main(){ // 主函数
int n; // 定义一个整型变量n
cin>>n; // 从标准输入读入一个整数n
if(is_prime(n)) cout<<"Yes"<<endl; // 如果n是素数,输出Yes
else cout<<"No"<<endl; // 如果n不是素数,输出No
return 0; // 返回0,表示程序正常结束
}
三.优化O(sqrt(n))
聪明的我们不难发现,当我们查找11是否为素数时,实则经历了以下比较:
11%2,11%3,11%4,11%5,11%6,11%7,11%8,11%9,11%10;
如果还不能发现问题的话,可以这样看,例如n=10时,要经历10%2,又要经历10%5,岂不浪费了吗?
其实我们只需要检查到即可。后面再检验就重复了。
#include<bits/stdc++.h> // 引入头文件,包含了所有标准库函数的声明
using namespace std; // 使用标准命名空间
bool is_prime(int n){ // 定义一个函数,判断一个数是否为素数
for(int i=2;i*i<n;i++){ // 从2开始遍历到sqrt(n)
if(n%i==0) return false; // 如果n能被i整除,说明n不是素数,返回false
}
return true; // 如果n不能被任何一个i整除,说明n是素数,返回true
}
int main(){ // 主函数
int n; // 定义一个整型变量n
cin>>n; // 从标准输入读入一个整数n
if(is_prime(n)) cout<<"Yes"<<endl; // 如果n是素数,输出Yes
else cout<<"No"<<endl; // 如果n不是素数,输出No
return 0; // 返回0,表示程序正常结束
}
四.埃氏筛法
若我们要找1-10000中的素数呢?那这样做的话就算是优化后的找素数,时间复杂度也太大了。
这时我们需要一个新的思路,没错,就是埃氏筛法。
埃氏筛法(Sieve of Eratosthenes)是一种用于找出一定范围内所有素数的算法。它的基本思想是从2开始,将每个素数的倍数都标记成合数,直到筛子无法再筛下去为止。最终留下的就是素数。
其实也就是先开个bool数组,从2开始找出所有倍数,将其标记为true,然后找下一个没被标记的数,继续重复以上操作,直到枚举到.
动图演示:
图来源与:(14条消息) 埃拉托色尼筛选法巧解质数问题(埃氏筛法求解素数问题)_质数筛选法动图_吴雨4的博客-CSDN博客
五.习题:
找出1-n有多少素数(n<100000)
这个程序的时间复杂度为O(nloglogn),可以处理更大的范围内的素数。
#include<bits/stdc++.h>
using namespace std;
const int MAX=100000; // 边界,具体取决于题目,本题为:n<100000;
bool prime[MAX]; // 默认false为素数。
void sieve(int n){
prime[1]=true; // 1不是素数
for(int i=2;i*i<=n;i++){ // 从2开始遍历到sqrt(n)
if(!prime[i]){ // 如果i是素数
for(int j=i*i;j<=n;j+=i){ // 将i的倍数标记成合数
prime[j]=true;
}
}
}
}
int main(){
int n;
cin>>n;
sieve(n); // 筛出n以内的素数
int ans=0; // 计数器,记录素数个数
for(int i=2;i<=n;i++){ // 遍历1-n之间的所有数
if(!prime[i]) ans++; // 如果i是素数,计数器加1
}
cout<<ans<<endl; // 输出素数个数
return 0;
}