输入一个整数n,输出n的约数为质数的数?两个问题n的约数问题和n的质数问题

9 篇文章 0 订阅
5 篇文章 0 订阅

一.首先解决n的质数的问题

(1)枚举法

       考虑质数的定义:在大于 1的自然数中,除了 1 和它本身以外不再有其他因数的自然数。因此对于每个数 x,我们可以从小到大枚举 [2,x−1] 中的每个数 y,判断 y是否为 x的因数。但这样判断一个数是否为质数的时间复杂度最差情况下会到 O(n),无法通过所有测试数据。
       就不写代码了

       枚举没有考虑到数与数的关联性,因此难以再继续优化时间复杂度。接下来我们介绍一个常见的算法,该算法由希腊数学家厄拉多塞(Eratosthenes\rm EratosthenesEratosthenes)提出,称为厄拉多塞筛法,简称埃氏筛。

(2)埃氏筛

以下是埃氏筛法的步骤:

1.创建一个大小为 n+1 的布尔数组 is_prime,并将所有元素初始化为 True。数组的索引代表数字,True 表示该数字是质数,False 表示该数字是合数。
2.将 is_prime[0] 和 is_prime[1] 设置为 False,因为 0 和 1 不是质数。
3.从索引 2 开始,遍历数组。如果当前索引 i 是质数(即 is_prime[i] 为 True),则将所有 i 的倍数(从 i^2开始,小于等于 n)标记为 False,表示这些数不是质数。
4.遍历完成后,所有 is_prime 数组中值为 True 的索引即为小于等于 n 的质数。

#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>

// 函数声明
void sieve_of_eratosthenes(int n);

int main() {
    int n = 30;
    printf("小于等于 %d 的质数:\n", n);
    sieve_of_eratosthenes(n);
    return 0;
}

// 实现埃拉托色尼筛法
void sieve_of_eratosthenes(int n) {
    // 动态分配一个布尔数组,并初始化为 true
    bool *is_prime = (bool*) malloc((n + 1) * sizeof(bool));
    for (int i = 0; i <= n; i++) {
        is_prime[i] = true;
    }

    is_prime[0] = is_prime[1] = false; // 0 和 1 不是质数

    for (int p = 2; p * p <= n; p++) {
        // 如果 is_prime[p] 没有被标记为 false,则 p 是一个质数
        if (is_prime[p] == true) {
            // 将所有 p 的倍数标记为 false
            for (int i = p * p; i <= n; i += p) {
                is_prime[i] = false;
            }
        }
    }

    // 打印所有的质数
    for (int p = 2; p <= n; p++) {
        if (is_prime[p]) {
            printf("%d ", p);
        }
    }
    printf("\n");

    // 释放动态分配的内存
    free(is_prime);
}

二.解决n的质数约数问题

要找出一个整数 n 的所有质数约数,我们可以通过以下步骤实现:

1.使用埃拉托色尼筛法生成小于等于 n 的所有质数。
2.遍历这些质数,检查它们是否是 n 的约数。
3.输出所有质数约数。

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

// 函数声明
void sieve_of_eratosthenes(int n, bool* is_prime);
void print_prime_factors(int n, bool* is_prime);

int main() {
    int n;
    printf("请输入一个整数: ");
    scanf("%d", &n);

    // 动态分配一个布尔数组,用于存储质数信息
    bool *is_prime = (bool*) malloc((n + 1) * sizeof(bool));
    sieve_of_eratosthenes(n, is_prime);
    
    printf("%d 的质数约数是: ", n);
    print_prime_factors(n, is_prime);
    
    // 释放动态分配的内存
    free(is_prime);
    
    return 0;
}

// 实现埃拉托色尼筛法
void sieve_of_eratosthenes(int n, bool* is_prime) {
    for (int i = 0; i <= n; i++) {
        is_prime[i] = true;
    }

    is_prime[0] = is_prime[1] = false; // 0 和 1 不是质数

    for (int p = 2; p * p <= n; p++) {
        if (is_prime[p] == true) {
            for (int i = p * p; i <= n; i += p) {
                is_prime[i] = false;
            }
        }
    }
}

// 打印 n 的质数约数
void print_prime_factors(int n, bool* is_prime) {
    for (int i = 2; i <= n; i++) {
        if (is_prime[i] && n % i == 0) {
            printf("%d ", i);
        }
    }
    printf("\n");
}

代码解析:
1.使用 sieve_of_eratosthenes 函数生成小于等于 n 的所有质数,并将结果存储在布尔数组 is_prime 中。
2.使用 print_prime_factors 函数遍历所有小于等于 n 的数,如果该数是质数且是 n 的约数,则将其打印出来。
3.在 main 函数中,输入一个整数 n,并调用上述两个函数来生成质数并打印质数约数。

  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值