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

完全数和质数算法详解

完全数是指一个正整数,它等于其所有真约数(即除了自身以外的所有正因数)之和。例如,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.mrgr.cn/news/92570.html

相关文章:

  • Ultralytics导出的Engine模型直接加载报错
  • 【缓存】缓存雪崩与缓存穿透:高并发系统的隐形杀手
  • STM32学习【4】ARM汇编(够用)
  • javaweb文件上传:@MultipartConfig注解与Apache Commons FileUpload对比
  • Visual Studio Code 远程开发方法
  • Metal学习笔记八:纹理
  • 【前端基础】Day 4 CSS盒子模型
  • springboot、deepseek4j、bge-m3和milvus
  • shell脚本的相关练习--->分支结构---->循环结构
  • Asp.Net Web API| React.js| EF框架 | SQLite|
  • 为AI聊天工具添加一个知识系统 之125 详细设计之66 智能语义网络
  • Axure PR 9 中继器 03 翻页控制
  • 51c嵌入式~电路~合集13
  • Mac本地部署Deep Seek R1
  • 如何正确理解mAP、精度、召回率等概念
  • Java类中的this操作
  • 【STM32F103ZET6——库函数】6.PWM
  • 【2025力扣打卡系列】子集型回溯
  • Ubuntu20.04下各类常用软件及库安装汇总
  • 什么是Ollama?什么是GGUF?二者之间有什么关系?