当前位置: 首页 > article >正文

完全数和质数算法详解

完全数是指一个正整数,它等于其所有真约数(即除了自身以外的所有正因数)之和。例如,6 是一个完全数,因为它的真约数是 1、2 和 3,且 1 + 2 + 3 = 6。

1 计算约数和

1.1 遍历

遍历其所有可能的约数并计算它们的和。如果和等于该数,则为完全数,否则不是。

#include <iostream>
using namespace std;

int main() {
    int N;
    cin >> N;
    while (N--) {
        int X;
        cin >> X;
        int sum = 0;
        for (int i = 1; i * i <= X; ++i) {
            if (X % i == 0) {
                if (i != X) sum += i; 
                int j = X / i;
                if (j != X && j != i) sum += j; 
            }
        }
        cout << X << (sum == X ? " is" : " is not") << endl;
    }
    return 0;
}

1.2 生成表

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

int main() {
    int N;
    cin >> N;
    vector<int> perfect = {6, 28, 496, 8128, 33550336}; 
    while (N--) {
        int X;
        cin >> X;
        bool isPerfect = false;
        for (int num : perfect) {
            if (num == X) {
                isPerfect = true;
                break;
            }
        }
        cout << X << (isPerfect ? " is" : " is not") << endl;
    }
    return 0;
}

2 判断质数

2.1 错误解法 遍历

#include <iostream>
using namespace std;

int main() {
    int n;
    cin >> n;
    for (int j = 1; j <= n; j++) {
        int x;
        bool is_prime = true;
        cin >> x;
        if (x == 1) 
            cout << x << " is not" << endl;
        else {
            int i;
            for (i = 2; i < x; i++) {
                if (x % i == 0) {
                    is_prime = false;
                    break;
                } else 
                    is_prime = true;
            }
            if (is_prime) 
                cout << x << " is" << endl;
            else 
                cout << x << " is not" << endl;
        }
    }
    return 0;
}

时间复杂度:对于每个输入的数字 x x x,内层循环从 2 2 2 x − 1 x-1 x1 遍历,因此单次判定的时间复杂度为 O ( x ) O(x) O(x)。如果需要判断 N N N 个数字,则总时间复杂度为 O ( N ⋅ X ) O(N \cdot X) O(NX),其中 X X X 是输入数字的最大值。当 X X X 较大(例如 1 0 9 10^9 109)时,通常会TLE


2.2 正确解法

根据数学原理,一个数 x x x 如果不是质数,那么它一定可以分解为两个因数 a a a b b b,且至少有一个因数小于等于 x \sqrt{x} x 。因此,我们只需要检查从 2 2 2 x \sqrt{x} x 的所有整数即可。

#include <iostream>
using namespace std;

int main() {
    int n;
    cin >> n;
    while (n--) {
        int x;
        bool is_prime = true;
        cin >> x;
        if (x == 1) 
            cout << x << " is not " << endl;
        else {
            int i;
            for (i = 2; i <= x / i; i++) {
                if (x % i == 0) {
                    is_prime = false;
                    break;
                }
            }
            if (is_prime) 
                cout << x << " is " << endl;
            else 
                cout << x << " is not " << endl;
        }
    }
    return 0;
}

时间复杂度: 对于每个数字 x x x,只需检查从 2 2 2 x \sqrt{x} x 的所有整数,因此单次判定的时间复杂度为 O ( x ) O(\sqrt{x}) O(x )。如果需要判断 N N N 个数字,则总时间复杂度为 O ( N ⋅ X ) O(N \cdot \sqrt{X}) O(NX ),其中 X X X 是输入数字的最大值。


为什么只需要检查到 x \sqrt{x} x

如果一个数 x x x不是质数,那么它一定可以分解为两个因数 a a a b b b,且至少有一个因数小于或等于 x \sqrt{x} x

一个数 x x x合数(非质数),意味着它可以被分解为两个整数的乘积: x = a ⋅ b x=a\cdot b x=ab,其中 a a a b b b都是大于1的整数。如果 x x x是质数,则它无法被任何小于 x x x的正整数整除(除了1和自身)。

假设 x x x是一个合数,那么它可以写成两个因数的乘积:
x = a ⋅ b x=a\cdot b x=ab
其中 a a a b b b都是正整数,且 a ≤ b a\leq b ab(为了简化讨论,我们可以假设 a a a是较小的那个因数)。
a ⋅ b = x    ⟹    a ≤ x 或 b ≤ x a\cdot b=x\implies a\leq\sqrt{x}\quad\text{或}\quad b\leq\sqrt{x} ab=xax bx

因为如果 a > x a>\sqrt{x} a>x b > x b>\sqrt{x} b>x ,那么 a ⋅ b > x ⋅ x = x a\cdot b>\sqrt{x}\cdot\sqrt{x}=x ab>x x =x,这与 a ⋅ b = x a\cdot b=x ab=x矛盾。因此,至少有一个因数 a a a b b b满足 a ≤ x a\leq\sqrt{x} ax b ≤ x b\leq\sqrt{x} bx 。换句话说,如果 x x x是合数,那么它一定存在一个小于或等于 x \sqrt{x} x 的因数。


反证法:

如果 x x x是合数,则它一定存在一个小于或等于 x \sqrt{x} x 的因数。

证明

  1. 假设 x x x是合数,且 x x x的所有因数都大于 x \sqrt{x} x
  2. x = a ⋅ b x=a\cdot b x=ab,其中 a a a b b b都是大于 x \sqrt{x} x 的整数。
  3. 根据假设, a > x a>\sqrt{x} a>x b > x b>\sqrt{x} b>x
  4. 因此, a ⋅ b > x ⋅ x = x a\cdot b>\sqrt{x}\cdot\sqrt{x}=x ab>x x =x,这与 x = a ⋅ b x=a\cdot b x=ab矛盾。
  5. 故假设不成立,即 x x x至少存在一个小于或等于 x \sqrt{x} x 的因数。

示例分析:

正例 x = 36 x=36 x=36

36 = 6 ⋅ 6 36=6\cdot6 36=66,其中 6 = 36 6=\sqrt{36} 6=36 。所有因数对为 ( 1 , 36 ) , ( 2 , 18 ) , ( 3 , 12 ) , ( 4 , 9 ) , ( 6 , 6 ) (1,36),(2,18),(3,12),(4,9),(6,6) (1,36),(2,18),(3,12),(4,9),(6,6)。只需要检查 2 , 3 , 4 , 5 , 6 2,3,4,5,6 2,3,4,5,6即可找到因数。

反例 x = 73 x=73 x=73

73 73 73是质数,无法分解为两个整数的乘积。检查 2 , 3 , 4 , 5 , 6 , 7 , 8 2,3,4,5,6,7,8 2,3,4,5,6,7,8后发现 73 73 73无法被整除。


http://www.kler.cn/a/547560.html

相关文章:

  • HBase高级技巧:解锁更强大的数据处理能力
  • 用大模型学大模型05-线性回归
  • C++类的简单介绍
  • SolidWorks速成教程P3-6【零件 | 第六节】——草图封闭轮廓所选轮廓厚度为零的报错
  • Unity Shader Graph 2D - Procedural程序化图形循环的箭头
  • openmv vs canmv 特征点检测 在线例程对比
  • python包的管理
  • 【第8章:深度学习框架与工具—8.1 TensorFlow与PyTorch的对比与选择建议】
  • 网页五子棋——用户模块
  • Vript-Hard——一个基于高分辨率和详细字幕的视频理解算法
  • TestHubo基础教程-创建项目
  • Python函数进阶250215
  • 从ARM官方获取自己想要的gcc交叉编译工具链接(Arm GNU Toolchain),并在Ubuntu系统中进行配置
  • 服务器模式部署mediacms后卸载mediacms,包括数据库
  • 项目版本号生成
  • CentOS 7上安装Python 3的步骤如下
  • 车规MCU处理器选择Cortex-M7还是Cortex-R52?
  • 树莓集团:从区域到全国,数字产业园服务如何有效赋能企业?
  • 【Erdas实验教程】004:影像镶嵌拼接
  • DeepSeek指导手册从入门到精通