质数又称素数。一个大于1的自然数,除了1和它自身外,不能被其他自然数整除的数叫做质数,否则称为合数。
规定1既不是质数也不是合数
分解质因数:把一个合数分解成若干个因数乘积的形式
分解质因数(也称分解素因数)只针对于合数
筛素数:将2~n之间的正整数放在数组内存储,将数组中2之后的所有能被2整除的数清0,再将3之后的所有能被3整除的数清0 ,以此类推,直到n为止。数组中不为0 的数即为素数。
质数定理:1~n只会有n/lnn个质数
暴力写法
bool is_prime(int n){
if(n<2) return false;
for(int i=2;i<n;i++)
if(n%i==0)
return false;
return true;
}
开平方写法(每次循环都要开平方,也是比较慢的,但比暴力快)
bool is_prime(int n){
if(n<2) return false;
for(int i=2;i<=sqrt(n);i++)
if(n%i==0)
return false;
return true;
}
i*i写法(n接近于int类型最大值时,i的平方<n时没有问题,当i+1的平方大于n时,i+1的平方会溢出,变为负数,影响判断)
bool is_prime(int n){
if(n<2) return false;
for(int i=2;i*i<n;i++)
if(n%i==0)
return false;
return true;
}
试除法判断质数(推荐写法)
bool is_prime(int n){
if(n<2) return false;
for(int i=2;i<=n/i;i++)
if(n%i==0)
return false;
return true;
}
筛质数(暴力写法)
void get_prime(int n){
for(int i=2;i<=n;i++){
if(!st[i]){//st[N]数组初始化全部为false
prime[cnt++]=i;//prime[N]数组用于存储质数 cnt用于计数 初始化为0
//如果是求质数个数 直接写cnt++
}
for(int j=i+i;j<=n;j+=i) st[j]=true;//将所有是i的倍数的数 变为true
//放到if外面 每次都会筛 放if里面只有是质数的时候才会筛
}
}
筛质数(埃氏筛法)
void get_prime(int n){
for(int i=2;i<=n;i++){
if(!st[i]){//st[N]数组初始化全部为false
prime[cnt++]=i;//prime[N]数组用于存储质数 cnt用于计数 初始化为0
//如果是求质数个数 直接写cnt++
for(int j=i+i;j<=n;j+=i) st[j]=true;//将所有是i的倍数的数 变为true
}
}
}
筛质数(线性筛法)
void get_prime(int n){
for(int i=2;i<=n;i++){
if(!st[i]) prime[cnt++]=i;//将质数存储到数组中
for(int j=0;prime[j]<=n/i;j++){
st[i*prime[j]]=true;//将该数与前面所有质数的乘积都消掉
//i=10时 可以与2、3、5、7相乘 即消20、30、50、70
//但30可以用i=15来消掉 多消一次
if(i%prime[j]==0) break;//如果没有这句 在i=10和i=15时都会筛30
//当i能被当前最小的质数整出时(当前整数就是i的最小质数) break
}
}
}