2.素数相关

定义及性质

质数又称为素数,是指在大于1的自然数中,除了1和它本身以外不再有其他因数的自然数。

只有两个正因数(1和自己)的自然数即为质数。比1大但不是素数的数称为合数。1和0既非素数也非合数。

所有大于1的正整数都可以表示成素数的和。所有的合数都可以写成一个素数乘以一个自然数的形式,这个素数被称为该合数的素因子。

判断一个数是否为素数

  1. 一个合数除它本身以外的最公约数小于等于它的平方根
/*************************************************************************
	> File Name: 2.is_prime_1.c
	> Author: 陈杰
	> Mail: 15193162746@163.com
	> Created Time: 2021年04月16日 星期五 09时57分33秒
  > 判断一个数是否是素数 时间复杂度 O(n^(1/2))
************************************************************************/
#include<stdio.h>
#include<math.h>
int is_prime(int x) {
    if(x < 2) return 0;
    for(int i = 2; i <= sqrt(x); i++) {
        if(x % i == 0) return 0;
    }
    return 1;
}
int main() {
    int n;
    scanf("%d", &n);
    printf("%s\n", is_prime(n) ? "Yes" : "No");
    return 0;
}
  1. 大于2的偶数都不是素数
/*************************************************************************
	> File Name: 2.is_prime_2.c
	> Author: 陈杰
	> Mail: 15193162746@163.com
	> Created Time: 2021年04月16日 星期五 09时57分33秒
  > 判断一个数是否是素数 时间复杂度 O((n^(1/2))/2)
************************************************************************/
#include<stdio.h>
#include<math.h>
int is_prime(int x) {
    if(x == 2) return 1;
    if(x < 2 || x % 2 == 0) return 0;
    for(int i = 3; i <= sqrt(x); i += 2) {
        if(x % i == 0) return 0;
    }
    return 1;
}
int main() {
    int n;
    scanf("%d", &n);
    printf("%s\n", is_prime(n) ? "Yes" : "No");
    return 0;
}
  1. 大于2素数均在6的倍数两侧
/*************************************************************************
	> File Name: 2.is_prime_3.c
	> Author: 陈杰
	> Mail: 15193162746@163.com
	> Created Time: 2021年04月16日 星期五 10时10分07秒
  > 判断一个数是否是素数 时间复杂度 O((n^(1/2))/6)
************************************************************************/
#include<stdio.h>
#include<math.h>
int is_prime(int x) {
    if(x == 2 || x == 3) return 1;
    if(x % 6 != 1 && x % 6 !=5 ) return 0;
    for(int i = 5; i <= sqrt(x); i += 6) {
        if(x % i == 0 || x % (i + 2) == 0) return 0;
    }
    return 1;
}
int main() {
    int n;
    scanf("%d", &n);
    printf("%s\n", is_prime(n) ? "Yes":"No");
    return 0;
}

素数筛

用素数来枚举合数,所有的合数都可以可写成:一个素数乘以一个大于1自然数。

/*************************************************************************
	> File Name: 2.is_prime_4.c
	> Author: 陈杰
	> Mail: 15193162746@163.com
	> Created Time: 2021年04月16日 星期五 10时30分58秒
  > 素数筛:判断10000内的一个大于1的自然数是否是素数 O(n*log n);
************************************************************************/
#include<stdio.h>
#define MAX_N 10000
int prime[MAX_N + 5];
// 构造函数,优先于main函数执行
__attribute__((constructor))
void init_prime() {
    for(int i = 2; i <= MAX_N; i++) {
        if(prime[i]) continue;              // i是合数
        for(int j = i; j < MAX_N / i; j++) {
            prime[i * j] = 1;               // 素数乘以一个大于本身的自然数为合数
        }
    }
}
int main() {
    int n;
    while(~scanf("%d", &n)) {
        if(n < 2 || n > 10000) break;
        printf("%s\n", prime[n] ? "No" : "Yes");
    }
    return 0;
}
素数筛扩展
  1. 输出n(n < 10000)以内的所有素数
/*************************************************************************
	> File Name: 2.is_prime_4_ex.c
	> Author: 陈杰
	> Mail: 15193162746@163.com
	> Created Time: 2021年04月16日 星期五 10时44分30秒
  > 用素数筛来枚举n以内的所有素数
************************************************************************/
#include<stdio.h>
int n;
int prime[10005];
void init_prime() {
    for(int i = 2; i <= n; i++) {
        if(prime[i]) continue;
        prime[++prime[0]] = i;          // i为素数,存储到已检测过的区域
        for(int j = i; j <= n / i; j++) {
            prime[i * j] = 1;
        }
    }
}
int main() {
    scanf("%d", &n);
    if(n < 2 || n > 10000) return 0;
    init_prime();
    for(int i = 1; i <= prime[0]; i++) {
        printf("%d\n", prime[i]);
    }
    return 0;
}
  1. N以内所有数字的最大/最小素因子
/*************************************************************************
	> File Name: 2.min_prime_factory.c
	> Author: 陈杰
	> Mail: 15193162746@163.com
	> Created Time: 2021年04月16日 星期五 10时56分38秒
  > 求一个数字的最小素因子
************************************************************************/
#include<stdio.h>
#define MAX_N 10000
int prime[MAX_N + 5];
__attribute__((constructor))
void prime_init() {
    for(int i = 2; i <= MAX_N; i++) {
        if(prime[i]) continue;
        for(int j = i; j <= MAX_N; j+= i) {
            if(prime[j]) continue;    // 求最大素因子,去掉此行就可以
            prime[j] = i;
        }
    }
}
int main() {
    int n;
    while(~scanf("%d", &n)) {
        if(n < 2 || n > MAX_N) break;
        printf("min_prime_factory[%d] = %d\n", n, prime[n]);
    }
    return 0;
}

线性筛

用素数来枚举合数,所有的合数都可以写成,一个素数乘以一个大于1自然数。线性筛是对素数筛的一个改进,通过统计素数进一步缩小了内部循环的次数。内部进行范围判断和赋值判断跳出循环,使得线性筛的时间复杂度接近O(n)

/*************************************************************************
	> File Name: 2.prime_list.c
	> Author: 陈杰
	> Mail: 15193162746@163.com
	> Created Time: 2021年04月16日 星期五 11时28分06秒
  > 线性筛枚举n以内的所有素数
 ************************************************************************/
#include<stdio.h>
int prime[10005];
void init_prime(int n) {
    for(int i = 2; i <= n; i++) {
        // 将素数存储到已检测过的区域
        if(!prime[i]) prime[++prime[0]] = i;
        // 枚举i以内的素数
        for(int j = 1; j <= prime[0]; j++) {
            // 超出数据范围退出循环
            if(prime[j] * i > n)  break;
            prime[prime[j] * i] = 1;
            // 已经找到i的最小素因子,退出循环(防止重复标记)
            if(i%prime[j] == 0) break;
        }
    }
}
int main() {
    int n;
    scanf("%d", &n);
    if(n < 2 || n > 10000) return 0;
    init_prime(n);
    for(int i = 1; i <= prime[0]; i++){
        printf("%d\n", prime[i]);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值