【C/C++】【基础数论】33、算数基本定理

算术基本定理,又称正整数的唯一分解定理。

说起来比较复杂,但是看一下案例就非常清楚了

任何一个大于 1 的正整数都可以唯一地分解成有限个质数的乘积形式,且这些质数按照从小到大的顺序排列,其指数也是唯一确定的。

例如,整数 60 可以分解为 2×2×3×5,这里的 2、3、5 都是质数,且这种分解方式是唯一的。

质数

如果一个数除了 1 和本身,没有其他的因数,就是质数。

合数

如果一个数除了 1 和本身,还有其他的因数,就是合数。

1 既不是质数,也不是合数。

一点一点过度,别着急,先看一下质数怎么判断

cpp 复制代码
#include <iostream>
using namespace std;

int main()
{
    int n;
    cin >> n;
    // 初始化标志变量,默认 n 是质数
    bool flag = true; 
    for (int i = 2; i <= n; i++)
    {
        // 如果 n 能被 i 整除
        if (n % i == 0) 
        {
            // 将标志变量设为 false,表示 n 不是质数
            flag = false; 
            // 跳出循环,因为已经确定 n 不是质数了
            break; 
        }
    }
    // 根据标志变量的值输出结果
    if (flag)
    {
        cout << n << "是质数。" << endl;
    }
    else
    {
        cout << n << "不是质数。" << endl;
    }
    return 0;
}

初学者是不是都这么写,可能还不屑注释,一堆字母就完事了?

这个写法没毛病,但是执行效率可能不是很高,因为所有的数都要从2到n来除一遍。来看看,稍微升级一点的写法,

cpp 复制代码
#include <iostream>
#include <cmath>
#include <limits>

int main() {
    int n;
    // 进入一个无限循环,直到输入有效为止
    while (true) {
        cout << "请输入一个正整数:";
        // 尝试读取输入到 n,如果读取成功并且 n 大于 1
        if (cin >> n && n > 1) {
            // 跳出循环,输入有效
            break;
        } else {
            // 清除输入流的错误状态标志
            cin.clear();
            // 忽略输入流中的剩余字符直到遇到换行符,防止错误输入影响后续输入
            cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
            cout << "输入无效,请重新输入。" << endl;
        }
    }

    bool isPrime = true;
    // 从 2 开始循环到 n 的平方根(优化后的质数判断范围)
    for (int i = 2; i <= sqrt(n); i++) {
        // 如果 n 能被 i 整除
        if (n % i == 0) {
            // 将标志变量设为 false,表示 n 不是质数
            isPrime = false;
            // 跳出循环,因为已经确定 n 不是质数了
            break;
        }
    }

    // 根据标志变量的值输出结果
    if (isPrime) {
        cout << n << "是质数。" << endl;
    } else {
        cout << n << "不是质数。" << endl;
    }

    return 0;
}

很多人可能像我一样刚开始学的时候一样,有个疑问。sqrt是干嘛的,为啥这么写。

在这段代码中,sqrt(n)表示对变量n取算术平方根。

  1. sqrt是 C++ 标准库中<cmath>头文件里定义的一个函数,它接受一个参数并返回该参数的算术平方根。
  2. 在这个代码片段中,通过遍历从 2 到sqrt(n)的整数来判断n是否为质数。这样做的目的是优化判断质数的过程。因为如果一个数n不是质数,那么它一定存在一个小于等于sqrt(n)的因子(除了 1 和n本身)。例如,如果n = 100,那么sqrt(100)=10,在判断 100 是否为质数时,只需要检查从 2 到 10 的整数是否能整除 100 即可,而不需要检查到 99,大大减少了循环次数,提高了程序的效率。

可以这么理解,一个数如果能被开平方得到一个新的整数,那么这个数一定不是质数。

因为能被开平方得到整数意味着该数存在一个相同的因数与其自身相乘得到这个数,比如 9 能被开平方为 3,9 = 3×3,有除了 1 和它本身之外的因数 3,所以不是质数。

比如 41 不能被开平方得到一个整数,41 是质数。

而质数只能被 1 和它自身整除,不存在可以开平方得到但是还是质数的情况的情况。

大大减少了循环次数,提高了程序的效率。

而算术基本定理又称正整数的唯一分解定理,它不完全等同于单纯的分解质因数,但可以通过分解质因数来体现。

算术基本定理指出:任何一个大于 1 的正整数都可以唯一地分解成有限个质数的乘积形式,且这些质数按照从小到大的顺序排列,其指数也是唯一确定的。

举个例子,整数 60 可以分解为,这里的 2、3、5 都是质数,且这种分解方式是唯一的。

而分解质因数只是实现算术基本定理的一种操作手段,算术基本定理强调的是正整数分解为质数乘积的唯一性这一本质属性。

一般我们编程思想和我们数学中用到的短除法非常的类似。简单来说,短除法就是不断地用最小的质因数除以它本身。

给你一个数,你怎么快速分解出他的质因数。就用这个方法。

比如100的质因数是2*2*5*5;那我们利用短除法来求一下。

我们用代码来拆解一下

cpp 复制代码
#include <iostream>
using namespace std;

int main()
{
    // 输入
    int n;
    cin >> n;

    // 输出提示信息
    cout << n << "的质因数分解为:";

    // 分解质因数
    for (int i = 2; i <= n; i++)
    {
        // 当 n 能被 i 整除时,进入循环
        while (n % i == 0)
        {
            // 输出质因数 i
            cout << i << " ";
            // 将 n 更新为 n 除以 i 的结果
            n /= i;
        }
    }
    cout << endl;
    return 0;
}

步骤说明:

  1. 首先从用户处获取一个整数n
    • int n; cin >> n;:定义变量n并读取用户输入的整数。
  2. 输出提示信息,让用户知道即将看到的是输入整数的质因数分解结果。
    • cout << n << "的质因数分解为:";:输出提示语句。
  3. i = 2开始尝试分解质因数,因为 2 是最小的质数。
    • for (int i = 2; i <= n; i++):循环从 2 开始,一直到等于n,确保所有可能的质因数都被考虑到。
  4. n能被i整除时,进入循环,不断输出i并更新n
    • while (n % i == 0):只要n能被i整除,就一直循环。
    • cout << i << " ";:输出找到的质因数i
    • n /= i;:将n更新为n除以i的结果,以便继续寻找下一个质因数。

例如,输入整数 120:

  1. 首先读取输入的 120。
  2. 输出提示信息 "120 的质因数分解为:"。
  3. i = 2开始:
    • 120 能被 2 整除,输出 2,n变为 60。
    • 60 能被 2 整除,再次输出 2,n变为 30。
    • 30 能被 2 整除,又输出 2,n变为 15。
  4. i = 3时:15 能被 3 整除,输出 3,n变为 5。
  5. i = 4不满足循环条件,继续下一个数。
  6. i = 5时:5 能被 5 整除,输出 5,此时n变为 1,循环结束。

最终输出结果为 "120 的质因数分解为:2 2 2 3 5"。

好了,有任何问题我们来评论区讨论一下吧

相关推荐
蓝天星空3 分钟前
Python调用open ai接口
人工智能·python
睡觉狂魔er4 分钟前
自动驾驶控制与规划——Project 3: LQR车辆横向控制
人工智能·机器学习·自动驾驶
Lenyiin5 分钟前
第146场双周赛:统计符合条件长度为3的子数组数目、统计异或值为给定值的路径数目、判断网格图能否被切割成块、唯一中间众数子序列 Ⅰ
c++·算法·leetcode·周赛·lenyiin
郭wes代码12 分钟前
Cmd命令大全(万字详细版)
python·算法·小程序
scan72427 分钟前
LILAC采样算法
人工智能·算法·机器学习
leaf_leaves_leaf29 分钟前
win11用一条命令给anaconda环境安装GPU版本pytorch,并检查是否为GPU版本
人工智能·pytorch·python
夜雨飘零134 分钟前
基于Pytorch实现的说话人日志(说话人分离)
人工智能·pytorch·python·声纹识别·说话人分离·说话人日志
菌菌的快乐生活1 小时前
理解支持向量机
算法·机器学习·支持向量机
爱喝热水的呀哈喽1 小时前
《机器学习》支持向量机
人工智能·决策树·机器学习
大山同学1 小时前
第三章线性判别函数(二)
线性代数·算法·机器学习