「数学::数论」分解质因子 / LeetCode 2521(C++)

c++实现分解质因数 题目描述 将一个正整数分解质因数。例如:输入90,输出 90=2*3*3*5。 输入 输入数据包含多行,每行是一个正整数n (1<n <100000) 。 输出 对于每个整数n将其分解质因数。 输入样例 90 256 199 输出样例 90=2*3*3*5 256=2*2*2*2*2*2*2*2 199=199 分解质因数听起来既熟悉又陌生,从小学就了... 阅读详情

概述

由算数基本定理,我们知道任意一个大于1的自然数可以表示为一些质数的乘积:

LeetCode 2521:

给你一个正整数数组 nums ,对 nums 所有元素求积之后,找出并返回乘积中 不同质因数 的数目。

注意:

  • 质数 是指大于 1 且仅能被 1 及自身整除的数字。
  • 如果 val2 / val1 是一个整数,则整数 val1 是另一个整数 val2 的一个因数。

示例 1:

输入:nums = [2,4,3,7,10,6]
输出:4
解释:
nums 中所有元素的乘积是:2 * 4 * 3 * 7 * 10 * 6 = 10080 = 25 * 32 * 5 * 7 。
共有 4 个不同的质因数,所以返回 4 。

思路

质因子:若a可整除x,且a为质数,则a为x的质因子。

明确一件事:

如果x存在大于\sqrt{x}的质数,则最多只存在一个,否则两个大于\sqrt{x}的质因数相乘会大于x。

也就是说我们可以质枚举小于\sqrt{x}的质因子,并在最后单独判断:

int cnt[N]{};       //cnt[i] = n 表示i是x的n个质因子
for (int i = 2; i * i <= x; i++) 
    while(!(x % i)) x /= i, cnt[i]++;
if (x != 1)...      //意味着当前x是原始x的最后的那一个大质因子

也就是在循环内部不断消耗可能的质因数,在最后脱离循环时,如果 x!=1,则当前x也为原始x的那个大于\sqrt{x}的质因数。

可以证明的是,while循环会保证x一定是被他的质因数消耗的。

例如,如果x不断被i=2消耗,则后续i=4时x已经无法再被消耗。

在循环条件中的i * i <= x看起来有点不对劲。由于while中x不断被消耗,这似乎不能保证i能够枚举到原始的终点。这其实不要紧,我们来证明这一点:

设原始x = P1^(K1) * P2^(K2) * ... *  Pn^(Kn) * Pt。

(Pi为一系列递增质数,Ki为对应的幂,Pt为唯一的大于根号\sqrt{x}的质数)

那么当i = P1,while完全消耗P1时,问题就等价于分解剩余的y = P2^(K2) * ... *  Pn^(Kn) * Pt。

由于P2>P1,接下来for循环使i从P1增长到P2时完全正确的。依旧,只需要循环i * i小于等于y。

同理,后续的分解也是如此。

在最后,单独判断最后的x,如果它不等于1,则意味着这是那个大质因子。


算法过程

对于本题,题目要求我们分解整个数组的乘积,但是比起先全部相乘再分解,不如逐一分解每个数组元素。

vector<int> cnt(1001);
    for (int num : nums){
        for (int i = 2; i <= 1000; i++){
            while (!(num % i)) 
                cnt[i]++, num /= i;
        }
    if (num != 1) cnt[num]++;
}

这种枚举有些低效,怎么优化呢? 


优化方案

还记得欧拉筛吗?「数学::质数」埃氏筛|欧拉筛(埃拉托斯特尼筛法|线性筛法)/ LeetCode 204(C++)

预处理是个很好的工作,先获取范围内所有的质数的数组prim,这样for循环的循环次数就大大降低了。

vector<int> cnt(N);
for (int num : nums){
    for (int i = 0; prim[i] * prim[i] <= num; i++){
        while (!(num % prim[i])) 
            cnt[prim[i]]++, num /= prim[i];
    }
    if (num != 1) cnt[num]++;
}
        

Code

constexpr int N = 1e3 + 1;
bool not_prim[N]{};
vector<int> prim;
auto init = []() -> int {
    for (int i = 2; i < N; i++) {
        if (!not_prim[i]) prim.push_back(i);
        for (int j = 0; i * prim[j] < N; j++) {
            not_prim[i * prim[j]] = true;
            if (!(i % prim[j])) break;
        }
    }
    return 0;
}();
class Solution {
public:
    int distinctPrimeFactors(vector<int>& nums) {
        vector<int> cnt(N);
        for (int num : nums){
            for (int i = 0; prim[i] * prim[i] <= num; i++){
                while (!(num % prim[i])) 
                    cnt[prim[i]]++, num /= prim[i];
            }
            if (num != 1) cnt[num]++;
        }
        return count_if(cnt.begin(), cnt.end(), [](int num) -> bool {return num;});
    }
};

复杂度

时间复杂度: O(nlogn) //分解单个数为logn

空间复杂度: O(n)         //预处理prim数组


总结

算术基本定理是初等数论中一条非常基本和重要的定理,它把对自然数的研究转化为对其最基本的元素——素数的研究。不觉得很酷吗?

如何快速分解质因数 教你如何快速分解质因数 阅读详情

相关推荐

【C++ 程序】 九九乘法表

程序 #include <iostream> using namespace std; int main() { cout << "┌────────┐" << endl; cout << "│ 1×1=1 │" << endl; for (int i = 2; i != 10; i++) { string blank; for (int k = 1; k != i; k++) { cout << "├

Teddy van Jerry的博客 1985

c++分解质因数详解

前面的求质数筛选法中,可以求出2到N的每个数i的最小质因数P[i]。j+=i)//i是质数时,删除i的倍数。把一个合数分解成若干个质因数的乘积的形式,即求质因数的过程叫做分解质因数。分解质因数的算式叫短除法,和除法的性质相似。A=A/P[A] ) //A迭代变小。请思考:程序的第20句中为什么如果i是因子就一定是质因子。已知A的最小质因数是P[A],令A’=A/P[A];对于求2到N的所有数分解质因数时,效率很高。性质1:质数分解的结果是唯一的。得到 360=2×2×2×3×3×5。参考程序3:(填空)

浪子回头 9901

C++ 分解质因数

把一个合数分解成若干个质因数乘积的形式(即求质数的过程)叫做分解质因数。分解质因数(也称分解素因数)只针对合数。   一个正整数n。   将n分解成质因数乘积的形式输出。【数据范围】 对于所有数据,2≤n≤20000。这道题最重要的是要明白不用判断是否是质数,因为若质数n未被整除,那么n的倍数(合数)一定也不能被整除,所以我们只要从2开始除,能整除就输出就好了。记得n一定要除以已经找出来的质数。 很简单,一看就会!!

小天狼星_布莱克 的博客 1万+

C++知识点总结(11):质因子分解

每个合数都可以写成几个质数相乘的形式,其中每个质数都是这个合数的因数,把每个质数都是这个合数的因数,把一个合数用质因数相乘的形式表示出来,叫做分解质因数。的上限,为了保证万无一失,我们来找一找因数和质因数之间的关系。现在小明想知道,在经过一系列操作以后,这个数最小可以变成多少?输出一个整数,表示游戏过程中最多可以进行多少次操作。是一个例外,既不是质数,也不是合数。是一个例外,既不是质数,也不是合数。和本身,没有其他的因数,就是质数。和本身,还有其他的因数,就是合数。输入共一行,包含一个整数。

joe_g12345的博客 8836

保姆级教程:用Ansible 2.9自动化配置华为ENSP路由器(附Cloud连接避坑指南)

本文提供了一份详细的Ansible 2.9与华为ENSP路由器自动化配置教程,涵盖环境搭建、网络连通性配置、Playbook开发及典型问题排查。特别针对Cloud连接常见问题提供避坑指南,帮助运维工程师快速掌握网络自动化技能,提升工作效率。

weixin_42561476的博客 376

深入解析NRF52832安全DFU Bootloader实现机制与蓝牙OTA升级流程

本文深入解析了NRF52832芯片安全DFU Bootloader的实现机制与蓝牙OTA升级流程。详细阐述了Bootloader的核心概念、双区升级策略、源码初始化流程以及蓝牙DFU服务的数据传输协议,并提供了从环境搭建、密钥生成到编译烧录、生成升级包的完整实战指南,帮助开发者构建安全可靠的无线固件更新系统。

weixin_29188043的博客 490

质因数算法(C/C++)

质因数算法(C/C++)

m0_71934846的博客 9290

VSCode + Clangd 配置避坑实录:从‘红波浪线’到完美代码提示的完整心路

本文详细记录了VSCode与Clangd配置过程中的常见问题及解决方案,从编译数据库生成到参数调优,帮助C++开发者快速解决代码提示失效、头文件找不到等问题,实现完美代码补全体验。重点介绍了Clangd与LLDB的集成配置及性能优化技巧,适用于Linux和跨平台开发环境。

weixin_28829479的博客 490

7.C++经典实例-分解质因数

执行时就会显示有错误,提示这个函数没有定义,这个时候,我们就得把函数定义到main之前。

fly_binbin的专栏 2548

Silvaco光电探测学习笔记(一)——有关响应和暗电流

习惯用md记笔记,索性发出来,一是为了在线同步,二是希望能帮到需要的人。

qq_41584406的博客 8012

行人检测模型在海思平台上的部署:从 PyTorch 到 NNIE 深度优化与实践

摘要 本文详细介绍行人检测模型从PyTorch到海思NNIE平台的部署流程。首先分析了行人检测面临的挑战(尺度变化、遮挡、姿态多样性等)及边缘部署的优势(实时性、隐私保护等)。重点阐述了模型转换过程:PyTorch→ONNX→Caffe→NNIE-WK,其中PyTorch转ONNX需注意评估模式设置、虚拟输入匹配、操作集版本选择等关键点。文章旨在帮助开发者在海思3516D芯片上实现高效的行人检测,克服部署过程中的常见问题,最终实现边缘设备的实时目标检测能力。

FJN110的博客 217

C++分解质因数

【问题描述】将一个正整数分解质因数,例如:输入90,输出90=2*3*3*5 【输入形式】一个正整数 【输出形式】所有质因子的乘积 【样例输入】90 【样例输出】90=2*3*3*5 //分解质因子 #include <iostream> using namespace std; int main() { int num; cin >> num; cout << num << "="; for (int i = 2; i ...

Shenrunchen的博客 3万+

深度学习特征融合(feature fusion)操作详解

特征融合是指在深度神经网络中,将来自不同来源(如不同网络分支、不同模态、不同时间步、不同空间尺度或不同抽象层级)的特征表示进行有策略地整合,以生成更具判别性、鲁棒性和语义丰富性的联合特征表示。其核心目标是最大化信息互补性,最小化信息冗余与噪声干扰。关键问题:如何“有效”融合?——这取决于任务需求、数据特性、计算资源和融合机制的设计。✅ 是否对齐了空间/通道/模态?✅ 融合方式是否与任务匹配?(检测需定位+语义 → 多尺度融合)✅ 是否引入可学习机制提升适应性?✅ 是否控制了计算开销?

浩瀚之水的专栏 793

质因子分解

所谓质因子分解是指将一个正整数n写成一个或多个指数的乘积的形式,例如6=2*3,8=2*2*2,180=2*2*2*3*3*5。或者也可以写成指数的形式,例如6=2^1*3^1,8=2^3,180=2^2*3^2*5^1。由此可以发现,质因子都是素数,不防先打印出其素数表,再进行记录。 由于每一个质因子都可以不止出现一次,因此不防定义结构体factor,用来存放质因子以及个数。如下: str...

分享包括但不限于计算机基础知识、数据结构与算法、Golang技术栈。年与时驰,意与日去,遂成枯落,多不接世,悲守穷庐,将复何及! 3615

AUTOSAR OS Counter讲解

Counter(计数器)以tick为单位记录操作系统中发生了多少“事情”。tick(滴答)是一个抽象的单位。时间,例如毫秒,微妙,分钟等,然后计数器计算过去了多少时间旋转,例如以度或分钟为单位,计数器计算物体旋转了多少按钮按下,计数器计算按钮按下多少次错误,计数器计算错误发生的频次中断(有时是任务)用于驱动一个计数器。该驱动程序负责进行正确的OS API调用来滴答计数器,或者告诉OS计数器已经滴答到一个所需的值。

酒无忧的博客 1073

第10章《VTK自定义部件Widget》

是用于交互式操作 3D 场景的组件,例如移动对象、调整尺寸、创建标注等。VTK 提供了一些内置的 Widget,如。,用户可以点击鼠标,在 3D 场景中放置一个点。负责绘制一个点,并控制其颜色、大小等。,可用于 3D 标注、对象拾取等应用!等,但在某些应用中,我们需要。这样,我们就创建了一个。

yumeiguo的博客 523

【C++】质因数分解问题详解与代码实现

质因数分解是数论中一个经典且基础的问题,不仅在数学研究中占据重要地位,同时也是许多现代计算机科学领域的关键组成部分。从数据加密(例如 RSA 算法)到分布式系统中的数据验证,质因数分解都扮演着不可或缺的角色。尽管这个问题看似简单,其高效解决方法和算法优化却蕴含着深刻的计算机科学与数学原理。本篇文章从基础定义入手,通过问题描述和算法设计,深入剖析质因数分解的实现方法,并结合 C++ 代码 展示具体应用。最后,我们将探讨其在现代技术中的实际应用及其未来优化方向,为读者提一个从 2024.12.9-✍55min

禅宗里有一个词叫做“因缘和合”。 所谓因缘,是指事件要发生所必须的条件。因缘和合就是当你聚集了这件事的一切条件,它就会自然而然的发生。“它就会自然而然的发生”,这种朴素而坚定的价值观让我们感到无比安心,安心到可以不用有任何担心焦虑。 2792

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

深入浅出质因数分解:原理与C++代码实现

深入浅出质因数分解:原理与C++代码实现

祯的博客 3438

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

[leetcode] 质因数分解

第一次参加周赛,遇到了质因数分解…

weixin_43742643的博客 1005

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

C++实现 质因数分解、最大公约数、最小公倍数、求所有因数

注:以下假设要求输入的正整数是long型 质因数分解(包含重复的质因子) 如:12 = 223 8 = 222 1既不是质数也不是合数 以下四种求解质因数的方法,都用统一的接口: //分解的质因数,从小到大,存储在数组 primeFactors 中 static void getPrimeFactors(long x, vector<long> & primeFactors) 前三种方法统一的思路: (1)p从2到x的范围上遍历,先找到x的最小质因子p (2)当x == p时,已经找完所

muyn547的博客 1万+

C++ 质数因子分解

功能:输入一个正整数,按照从小到大的顺序输出它的所有质因子(重复的也要列举)(如180的质因子为2 2 3 3 5 )按照从小到大的顺序输出它的所有质数的因子,以空格隔开。输出:2 2 3 3 5。

GPU全栈博主 1257

质因数分解算法C++实现

算法思想:对n进行分解质因数,应先找到一个最小的质数k,然后按下述步骤完成: (1)如果这个质数恰等于n,则说明分解质因数的过程已经结束,打印出即可。 (2)如果n<>k,但n能被k整除,则应打印出k的值,并用n除以k的商,作为新的正整数你n,  重复执行第一步。 (3)如果n不能被k整除,则用k+1作为k的值,重复执行第一步。 #include "stdio.h" #incl...

一面之媛 1万+

C++实现质因数分解

质数(prime number)又称素数,有无限个。一个大于1的自然数,除了1和它本身外,不能被其他自然数整除(除0以外)的数称之为素数(质数);否则称为合数。根据算术基本定理,每一个比1大的整数,要么本身是一个质数,要么可以写成一系列质数的乘积;而且如果不考虑这些质数在乘积中的顺序,那么写出来的形式是唯一的。最小的质数是2。

坚持 5万+
上一篇: 「STL::array」标准库容器:array(数组)介绍(C++)
下一篇: 「动态规划::线性DP」最长上升子序列(LIS)|编辑距离 / LeetCode 300|72(C++)
Daking-
博客等级 码龄3年 912粉丝 70原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值