素数判断
素数题,是蓝桥杯常考题型之一,下面就跟我来学习素数的几种常见写法把。
素数(也叫质数):指在大于1的自然数中 ,除了1和该数自身外,无法被其他自然数整除的数 (也可定义为只有1与该数本身两个正因数的数)。大于1的自然数若不是素数,则称之为合数(也称为合成数),其中根据定义数字2,就是最小的素数
一、暴力写法
题目:判断数字n,是不是质数
如果暴力直接写的话,直接根据定义判断从2~n-1,没有可以被n整除的数,那么n就是质数了。
代码如下:
#include<bits/stdc++.h>
using namespace std;
int n;
bool flag = true;
int main(){
cin >> n;
for(int i = 2; i < n; i++){
if (n % i == 0){//n与i的余数为零,即代表可以整除
flag = false;
break;
}
}
cout << (flag ? "n 是素数" : "n 不是素数");//三目运算 flag 为真执行 :前面的语句,反之执行后面的语句
}
二、试除法(暴力的优化)
题目:还是一样的
原理:此一程序将n除以每个大于1且小于等于的平方根之整数m,若存在一个相除为整数的结果,则n不是素数;反之则是个素数。实际上,若是个合数(其中与b!=1),则其中一个约数b必定至大为 n \sqrt{n} n
简而言之:就是原来判断2~ n-1,现在判断2~ n \sqrt{n} n
代码如下:
#include<bits/stdc++.h>
using namespace std;
int n;
bool flag = true;
int main(){
cin >> n;
for(int i = 2; i*i < n; i++){ //也可以写成i < pow(n,0.5),写成这样怕你们看不懂(狗头)
if (n % i == 0){//n与i的余数为零,即代表可以整除
flag = false;
break;
}
}
cout << (flag ? "n 是素数" : "n 不是素数");//三目运算 flag 为真执行 :前面的语句,反之执行后面的语句
}
三、埃式筛法(也称素数筛)
题目:还还是一样的
按我的理解:素数的倍数一定不是质数,因为,因为他的倍数可以被,当前的素数整除呀!所以,简而言之,素数的倍数不是素数,把这些,不是素数去掉就OK了
代码如下:
#include<bits/stdc++.h>
using namespace std;
const int maxl = 1e5+5;
int n;
bool flag[maxl];
int main(){
memset(flag, 1, sizeof(flag));
cin >> n;
for (int i = 2; i <= n; i++){
if (flag){
for (int j = 2 * i; j <= n; j += i){//这里把每个质数i的倍数给去掉(flag[j]变成false)
flag[j] = false;
}
}
}
cout << (flag[n] ? "n 是素数" : "n 不是素数");//三目运算 flag 为真执行 :前面的语句,反之执行后面的语句
}
四、欧拉筛
题目:还是一样
原理:用已知的质数筛掉这个质数的倍数。且需要保证对于任意一个合数,它会且只会它的最小因数筛掉
简而言之:欧拉比埃式筛法是它不会重复标j记一个数是不是素数的倍数
代码如下:
#include<bits/stdc++.h>
using namespace std;
bool flag[100001]={1,1};//i=0,i=1的时候都不是质数 ,所以直接标记
int b[100001], n;//b存质数
int k;
int main(){
cin>>n;
for(int i = 2;i <= 100001;i++){
if (!flag[i]){
b[++k]=i;
}
for(int j = 1;j <= k;j++){
if(i * b[j] > 100001)break;// 如果超出给出的范围,那么就退出循环
a[i * [j]] = 1;//用质数数依次×i,结果标记为合数(也就是标记为1)。
if(i % b[j] == 0)break;//最关键的只标记一次
}
}
cout << (flag[n] ? "n 是素数" : "n 不是素数");//三目运算 flag 为真执行 :前面的语句,反之执行后面的语句
}