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

概述

由算数基本定理,我们知道任意一个大于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数组


总结

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/68394.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

docker-compose Zookeeper 集群搭建

文章目录 前言docker-compose Zookeeper 集群搭建1. Zookeeper下载2. 制作Dockerfile文件3. 构建镜像4. docker-compose 管理5. docker-compose构建/启动6. 验证6.1 docker ps6.2 使用 zkCli.sh 连接并验证集群 前言 如果您觉得有用的话&#xff0c;记得给博主点个赞&#xff0…

WIN11 UEFI漏洞被发现, 可以绕过安全启动机制

近日&#xff0c;一个新的UEFI漏洞被发现&#xff0c;可通过多个系统恢复工具传播&#xff0c;微软已经正式将该漏洞标记为追踪编号“CVE-2024-7344”。根据报告的说明&#xff0c;该漏洞能让攻击者绕过安全启动机制&#xff0c;并部署对操作系统隐形的引导工具包。 据TomsH…

R语言学习笔记之高效数据操作

一、概要 数据操作是R语言的一大优势&#xff0c;用户可以利用基本包或者拓展包在R语言中进行复杂的数据操作&#xff0c;包括排序、更新、分组汇总等。R数据操作包&#xff1a;data.table和tidyfst两个扩展包。 data.table是当前R中处理数据最快的工具&#xff0c;可以实现快…

【数据结构】 并查集 + 路径压缩与按秩合并 python

目录 前言模板朴素实现路径压缩按秩合并按树高为秩按节点数为秩 总结 前言 并查集的基本实现通常使用森林来表示不同的集合&#xff0c;每个集合用一棵树表示&#xff0c;树的每个节点有一个指向其父节点的指针。 如果一个节点是它自己的父节点&#xff0c;那么它就是该集合的代…

低代码系统-产品架构案例介绍、得帆云(八)

产品名称 得帆云DeCode低代码平台-私有化 得帆云DeMDM主数据管理平台 得帆云DeCode低代码平台-公有云 得帆云DePortal企业门户 得帆云DeFusion融合集成平台 得帆云DeHoop数据中台 名词 概念 云原生 指自己搭建的运维平台&#xff0c;区别于阿里云、腾讯云 Dehoop 指…

【PyTorch】5.张量索引操作

目录 1. 简单行、列索引 2. 列表索引 3. 范围索引 4. 布尔索引 5. 多维索引 个人主页&#xff1a;Icomi 在深度学习蓬勃发展的当下&#xff0c;PyTorch 是不可或缺的工具。它作为强大的深度学习框架&#xff0c;为构建和训练神经网络提供了高效且灵活的平台。神经网络作为…

基于微信小程序高校课堂教学管理系统 课堂管理系统微信小程序(源码+文档)

目录 一.研究目的 二.需求分析 三.数据库设计 四.系统页面展示 五.免费源码获取 一.研究目的 困扰管理层的许多问题当中,高校课堂教学管理也是不敢忽视的一块。但是管理好高校课堂教学又面临很多麻烦需要解决,如何在工作琐碎,记录繁多的情况下将高校课堂教学的当前情况反…

论文阅读笔记:VMamba: Visual State Space Model

论文阅读笔记&#xff1a;VMamba: Visual State Space Model 1 背景2 创新点3 方法4 模块4.1 2D选择性扫描模块&#xff08;SS2D&#xff09;4.2 加速VMamba 5 效果5.1 和SOTA方法对比5.2 SS2D和自注意力5.3 有效感受野5.4 扫描模式 论文&#xff1a;https://arxiv.org/pdf/240…

【文星索引】搜索引擎项目测试报告

目录 一、项目背景二、 项目功能2.1 数据收集与索引2.2 API搜索功能2.3 用户体验与界面设计2.4 性能优化与维护 三、测试报告3.1 功能测试3.2 界面测试3.3 性能测试3.4 兼容性测试3.5 自动化测试 四、测试总结4.1 功能测试方面4.2 性能测试方面4.3 用户界面测试方面 一、项目背…

DBO-高斯回归预测matlab

蜣螂优化算法(Dung Beetle Optimizer, DBO)是一种新型的群智能优化算法&#xff0c;在2022年底提出&#xff0c;主要是受蜣螂的的滚球、跳舞、觅食、偷窃和繁殖行为的启发。 本次研究使用的是 Excel 格式的股票预测数据。数据集按照 8&#xff1a;1&#xff1a;1 的比例&#x…

java后端之事务管理

Transactional注解&#xff1a;作用于业务层的方法、类、接口上&#xff0c;将当前方法交给spring进行事务管理&#xff0c;执行前开启事务&#xff0c;成功执行则提交事务&#xff0c;执行异常回滚事务 spring事务管理日志&#xff1a; 默认情况下&#xff0c;只有出现Runti…

【嵌入式】总结——Linux驱动开发(三)

鸽了半年&#xff0c;几乎全忘了&#xff0c;幸亏前面还有两篇总结。出于快速体验嵌入式linux的目的&#xff0c;本篇与前两篇一样&#xff0c;重点在于使用、快速体验&#xff0c;uboot、linux、根文件系统不作深入理解&#xff0c;能用就行。 重新梳理一下脉络&#xff0c;本…

RabbitMQ 多种安装模式

文章目录 前言一、Windows 安装 RabbitMq1、版本关系2、Erlang2.1、下载安装 Erlang 23.12.2、配置 Erlang 环境变量 3、RabbitMQ3.1、下载安装 RabbitMQ 3.8.93.2、环境变量3.3、启动RabbitMQ 管理插件3.3、RabbitMQ3.4、注意事项 二、安装docker1、更新系统包&#xff1a;2、…

使用python-docx包进行多文件word文字、字符批量替换

1、首先下载pycharm。 2、改为中文。 3、安装python-docx包。 搜索包名字&#xff0c;安装。 4、新建py文件&#xff0c;写程序。 from docx import Documentdef replace1(array1):# 替换词典&#xff08;标签值按实际情况修改&#xff09;dic {替换词1: array1[0], 替换…

Android中Service在新进程中的启动流程

目录 1、Service与AMS交互框架介绍 1.1、认识AMS代表IActivityManager 1.2、认识客户端代表IApplicationThread 2、Service启动流程概览 我们知道Android有四大组件&#xff0c;Activity、Service、ContentProvider、Broadcast&#xff0c;每个组件在系统运行中或者我们编写…

read+write实现:链表放到文件+文件数据放到链表 的功能

思路 一、 定义链表&#xff1a; 1 节点结构&#xff08;数据int型&#xff09; 2 链表操作&#xff08;创建节点、插入节点、释放链表、打印链表&#xff09;。 二、链表保存到文件 1打开文件 2遍历链表、写文件&#xff1a; 遍历链表,write()将节点数据写入文件。…

【景区导游——LCA】

题目 代码 #include <bits/stdc.h> using namespace std; using ll long long; const int N 1e5 10; const int M 2 * N; int p[N][18], d[N], a[N]; ll dis[N][18]; //注意这里要开long long int h[N], e[M], ne[M], idx, w[M]; int n, k; void add(int a, int b, …

二进制安卓清单 binary AndroidManifest - XCTF apk 逆向-2

XCTF 的 apk 逆向-2 题目 wp&#xff0c;这是一道反编译对抗题。 题目背景 AndroidManifest.xml 在开发时是文本 xml&#xff0c;在编译时会被 aapt 编译打包成为 binary xml。具体的格式可以参考稀土掘金 MindMac 做的类图&#xff08;2014&#xff09;&#xff0c;下面的博…

反向代理模块。。

1 概念 1.1 反向代理概念 反向代理是指以代理服务器来接收客户端的请求&#xff0c;然后将请求转发给内部网络上的服务器&#xff0c;将从服务器上得到的结果返回给客户端&#xff0c;此时代理服务器对外表现为一个反向代理服务器。 对于客户端来说&#xff0c;反向代理就相当于…

flink StreamGraph解析

Flink程序有三部分operation组成&#xff0c;分别是源source、转换transformation、目的地sink。这三部分构成DAG。 DAG首先生成的是StreamGraph。 用户代码在添加operation的时候会在env中缓存&#xff08;变量transformations&#xff09;&#xff0c;在env.execute()执行的…