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

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

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

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

任何一个大于 1 的正整数都可以唯一地分解成有限个质数的乘积形式,且这些质数按照从小到大的顺序排列,其指数也是唯一确定的。
例如,整数 60 可以分解为 2×2×3×5,这里的 2、3、5 都是质数,且这种分解方式是唯一的。

质数

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

合数

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

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

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

#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来除一遍。来看看,稍微升级一点的写法,

#include <iostream>
#include <cmath>
#include <limits>int main() {int n;// 进入一个无限循环,直到输入有效为止while (true) {cout << "请输入一个正整数:";// 尝试读取输入到 n,如果读取成功并且 n 大于 1if (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;那我们利用短除法来求一下。

我们用代码来拆解一下

#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){// 输出质因数 icout << 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”。

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

相关文章:

  • 选择租用徐州存储服务器有什么作用?
  • 数据库系列(1)常见的四种非关系型数据库(NoSQL)
  • 前端Vue学习笔记02
  • go的结构体、方法、接口
  • 【1分钟学会】实用的Git工作流程
  • 初学51单片机之I2C总线与E2PROM
  • 追随 HarmonyOS NEXT,Solon v3.0 将在10月8日发布
  • 基于饥饿游戏搜索优化随机森林的数据回归预测 MATLAB 程序 HGS-RF
  • Could not find com.mapbox.mapboxsdk:mapbox-android-accounts:0.7.0.解决
  • STM32G431RBT6(蓝桥杯)串口(发送)
  • RTX NVIDIA 3090卡配置对应pytorch,CUDA版本,NVIDIA驱动过程及问题整理
  • MATLAB基本语句
  • 【最基础最直观的排序 —— 冒泡排序算法】
  • 基础漏洞——SSRF
  • 【FasAPI】使用FastAPI来实现一个基于RBAC(基于角色的访问控制)的用户权限控制系统
  • [LeetCode] Wiggle Sort
  • 2017 年终总结 —— 在路上
  • 77. Combinations
  • JSDuck 与 AngularJS 融合技巧
  • MYSQL 的 IF 函数
  • Node.js 新计划:使用 V8 snapshot 将启动速度提升 8 倍
  • Python_网络编程
  • python学习笔记 - ThreadLocal
  • Redis学习笔记 - pipline(流水线、管道)
  • SpiderData 2019年2月16日 DApp数据排行榜
  • Theano - 导数
  • 包装类对象
  • 开源SQL-on-Hadoop系统一览
  • 漫谈开发设计中的一些“原则”及“设计哲学”
  • 每个JavaScript开发人员应阅读的书【1】 - JavaScript: The Good Parts
  • 前端 CSS : 5# 纯 CSS 实现24小时超市
  • 前端之Sass/Scss实战笔记
  • 时间复杂度与空间复杂度分析
  • 使用common-codec进行md5加密
  • 听说你叫Java(二)–Servlet请求
  • 微信小程序设置上一页数据
  • Spring Batch JSON 支持
  • ​低代码平台的核心价值与优势
  • ​如何在iOS手机上查看应用日志
  • #免费 苹果M系芯片Macbook电脑MacOS使用Bash脚本写入(读写)NTFS硬盘教程
  • (Redis使用系列) Springboot 使用redis实现接口幂等性拦截 十一
  • (附源码)计算机毕业设计ssm电影分享网站
  • (附源码)计算机毕业设计高校学生选课系统
  • (免费领源码)python#django#mysql校园校园宿舍管理系统84831-计算机毕业设计项目选题推荐
  • (十二)devops持续集成开发——jenkins的全局工具配置之sonar qube环境安装及配置
  • .cn根服务器被攻击之后
  • .mkp勒索病毒解密方法|勒索病毒解决|勒索病毒恢复|数据库修复
  • .NET 4.0中的泛型协变和反变
  • .Net FrameWork总结
  • .net 调用php,php 调用.net com组件 --
  • .NET 服务 ServiceController
  • .NET/C# 使窗口永不激活(No Activate 永不获得焦点)
  • .NET3.5下用Lambda简化跨线程访问窗体控件,避免繁复的delegate,Invoke(转)
  • .NET建议使用的大小写命名原则
  • /etc/fstab 只读无法修改的解决办法