蓝蓝计算机考研算法-day01判断素数和计算完全数

304 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 24 天,点击查看活动详情

Day01 2023/02/27

难度:简单

题目1

从键盘输入一个整数,判断该数是否为素数(质数)。素数是指再大于1的自然数中,除了1和它本身以外不再有其他因数的自然数。

题目2

求解从2到20000的所有完全数,完全数是指它所有的真因子(即除了自身以外的约数)的和(即因子函数),恰好等于它本身。 例如:28,它有约数1、2、4、7、14、28,除去它本身28外,其余5个数相加,1+2+4+7+14=28。

示例1

输入: 3
输出: 3是素数

示例2

输入: 20000
输出: 6 2 8496 8128
说明: 输出了2~20000内的完全数

思路1


  • 根据素数的定义可知,假设这个数是n,那么从2~(n-1)之间,任取一个数和n进行“n%该数”的操作,如果都不能整除的话,该数就为素数。
  • 当然上述方法可以继续优化一下减少循环的次数,其实任何正整数的约数都是成对出现的,例如:12它的约数队分别是(1,12)(2,6) (3,4) ,所以我们只需要判断左边或者是右边的约数,是否满足素数的要求即可,左右队约数的分界线为自身的平方根。本题就采用这种优化过的方法。

思路2


  • 这里求解完全数,最直接的方法就是暴力解法,根据完全数的定义,计算2~20000范围内每个数的真因子(即除了自身以外的约数)之和,如果等于本身,即该数就是完全数,接着输出它即可。
  • 当然暴力解法的时间复杂度较高为O(n2)O(n^2),这里我们介绍一种优化过时间复杂度的一种方法,使用欧拉公式计算完全数。
    欧拉公式说明:
  1. 如果pp是质数,且2p12^p-1也是质数,那么(2p1)2p1(2^p-1)*2^{p-1}便是一个完全数。

  2. 例如p=2p=2,是一个质数,2p1=32^p-1=3也是质数,(2p1)2p1=32=62^p-1)*2^{p-1}=3*2=6是完全数。

  3. 例如p=3p=3,是一个质数,2p1=72^p-1=7也是质数,(2p1)2p1=74=282^p-1)*2^{p-1}=7*4=28是完全数。

关键点


  • 第一个问题也是求解第二个问题的一部分及判断该数是否为素数(质数)

算法实现


c++代码实现-优化后的方法

#include <cmath>
#include <iostream>
using namespace std;

//问题一:判断是否为素数(质数)
bool is_prime(int p) {
    for (int i = 2; i <= sqrt(p); i++) //判断是否有除了1和自生的因数(约数)
        if (p % i == 0)
            return false;
    return true;
}

//问题二:求完全数
// 方法:欧拉公式
// 如果p是质数,且2^p-1也是质数,那么(2^p-1)X2^(p-1)便是一个完全数
int main() {
    int n;
    cin >> n;
    for (int p = 2; p <= n; p++) { //1肯定不是完全数
        int t = pow(2, p) - 1;
        if (is_prime(p) && is_prime(t)) { // 调用is_prime方法,判断是否满足欧拉方程的要求,计算完全数
            int perfect_num = pow(2, p - 1) * t;
            if (perfect_num <= n)
                cout << perfect_num << ' ';
            else
                break; //当大于n时就跳出循环,大大降低了循环次数
        }
    }
}

判断是否为素数:

  • 时间复杂度 O(m)O(m)---循环m次,其中m为该数的平方根
  • 空间复杂度 O(1)O(1)---都是常数级的辅助变量,除此没有额外的辅助空间

求完全数:

  • 时间复杂度 O(mn)O(m*n)--- 判断是否为素数要,循环m次,其中m为该数的平方根 ,在此基础上,判断范围内的完全数,外层还有一个for循环,在最坏情况下循环n次,其中n为范围大小
  • 空间复杂度 O(1)O(1)---都是常数级的辅助变量,除此没有额外的辅助空间

总结

这两题,都介绍了最常规的方法,和经过优化后的方法,如果实在不明白优化后的方法,也可以使用常规方法。