质数判定与筛选等(C/C++)

1. 质数判定

 解析:质数判定从2 — n - 1都不会被整除即可
 优化:不需要判定到 n - 1这么远,而只需要判定到根号 n 的位置,原因很简单假如你大于根号n之后还可以判定其可以整除,那么它一定是由一个大于根号n 和小于根号n 的两个整数相乘得到结果,所以这个结果的判定一定可以在小于根号n的时候完成。
在这里插入图片描述

**判断是否为质数
bool is_prime(int x){
    if(x == 1) return false;
    for(int i = 2 ; i <= x / i ; i ++ ){
        if(x % i == 0) return false;
    }
    return true;
}

2. 质数分解

 解析:与前面相似从小到大筛选其质数,如果是其质数则不断除去即可
 注意:最后可能会剩下一个质数,需要判定其是否存在

#include<iostream>
using namespace std;
int n, x;
void divide(int x){
    for(int i = 2 ; i <= x / i ; i ++ ){
        if(x % i == 0){
            int s = 0;
            while(x % i == 0){
                x /= i;
                s ++ ;
            }
            cout << i << ' ' << s << endl; // i 的 s 次方 组成
        }
    }
    if(x > 1){ // 是否有质数剩余
        cout << x << ' ' << 1 << endl;
    }
}
int main(){
    cin >> n;
    while(n -- ){
        cin >> x;
        divide(x);
    }
}

3. 质数筛选

 普通筛法:和质数筛选方法相似,因为合数是由较小的质数乘积组成,所以当我们遇到质数就用去删去其后由这个质数组成的合数即可。
 线性筛法:保证合数只会被其最小的质数乘积筛去
 线性筛法原理:核心就是用其前面求出来的质数和 i 进行相乘进行筛选,因为筛选出来的数是由最小的质数和 i 乘积筛去的,知道 i % primes[ j ] == 0时跳出循环,因为如果再继续筛去,其值是用 i 筛去的,而 i 还有更小的质因子也就是之前的primes[ j ]. 当i能被当前的质数整除时(当前整数就是i的最小质数)
例如下图线性筛法解析:
在这里插入图片描述

// 普通筛法
#include<iostream>
using namespace std;
const int N = 1e6 + 10;
int n, s = 0;
bool st[N];
int main(){
    cin >> n;
    for(int i = 2 ; i <= n ; i ++ ){
        if(st[i]) continue; // 合数跳过
        s ++ ;
        for(int j = i ; j <= n ;j += i) st[j] = true; // 删去之后由这个质数乘积得到的合数
    }
    cout << s << endl;
}

线性筛法核心
if(i % primes[ j ] != 0) primes[j] 就是 primes[ j ] * i 的最小质因子(因为是从前向后碰到的第一个质因子必定就是最小的了)
if(i % primes[ j ] == 0) primes[j] 就是 primes[ j ] * i 的最小质因子,并且也是 i 的最小质因子,之后如果继续用 i 筛去别的数字就是不正确的(因为它们本需要用primes[j]作为最小质因子去筛掉) 所以这时候需要跳出循环


**筛选质数(线性筛法)
#include<iostream>
using namespace std;
const int N = 1e6 + 10;
int n, s = 0, primes[N];
bool st[N];

int main(){
    cin >> n;
    for(int i = 2 ; i <= n ; i ++ ){
        if(!st[i]) primes[s ++] = i; // 加入为质数
        for(int j = 0 ; primes[j] <= n / i ; j ++ ){
            st[primes[j] * i] = true; // 筛去
            if(i % primes[j] == 0) break; // 跳出循环,不能继续筛,
    //因为之后下一个假设为j + 1再筛去的部分是用primes[j + 1] * i 筛去的, 
    //而其实 primes[j + 1] * i的最小质数不是primes[j + 1] 或者 i 而是之前的primes[j]
        }
    }
    cout << s << endl;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

psudd

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值