「数学::质数」分解质因子 / 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…

Vue.js 使用 Vuex 管理组件间的共享状态

Vue.js 使用 Vuex 管理组件间的共享状态 今天咱们来聊聊如何用 Vuex 来管理 Vue.js 应用中各个组件之间的共享状态。如果你曾经在项目中为了让组件共享数据而头疼&#xff0c;那么这篇文章就是为你准备的。 什么是 Vuex&#xff1f; 简单来说&#xff0c;Vuex 就是 Vue.js 的…

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;可以实现快…

本地大模型编程实战(04)给文本自动打标签

文章目录 准备实例化本地大模型情感分析更精细的控制总结代码 使用本地大模型可以根据需要给文本打标签&#xff0c;本文介绍了如何基于 langchain 和本地部署的大模型给文本打标签。 本文使用 llama3.1 作为本地大模型&#xff0c;它的性能比非开源大模型要查一下&#xff0c;…

视频外绘技术总结:Be-Your-Outpainter、Follow-Your-Canvas、M3DDM

Diffusion Models专栏文章汇总:入门与实战 前言:视频Inpaint的技术很火,但是OutPaint却热度不高,这篇博客总结比较经典的几篇视频Outpaint技术。其实Outpaint在runway等工具上很火,可是学术界对此关注比较少,博主从这三年的顶会中找到了最具代表性的三篇论文解读。 目录 …

Java对象注入的常见方式

在 Java 中&#xff0c;对象注入&#xff08;依赖注入&#xff0c;Dependency Injection&#xff09;是实现松耦合设计的重要方式&#xff0c;常见的有以下几种实现形式&#xff1a; 1. 构造器注入&#xff08;Constructor Injection&#xff09; 通过类的构造函数注入依赖对象…

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

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

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

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

.NET 8 项目 Docker 方式部署到 Linux 系统详细操作步骤

本文将详细介绍如何将一个 .NET 8 项目通过 Docker 部署到 Linux 系统中。以下步骤包括从项目的创建、Dockerfile 的编写、镜像构建、到最后在 Linux 上的容器运行。 1. 环境准备 在开始之前&#xff0c;请确保你已经具备以下环境&#xff1a; Linux 系统&#xff08;如 Ubu…

【PyTorch】5.张量索引操作

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

springboot 动态线程池

在Spring Boot中&#xff0c;可以使用ThreadPoolTaskExecutor类来创建动态线程池。以下是一个示例&#xff1a; 首先&#xff0c;需要在配置文件中配置线程池的属性&#xff0c;例如最小线程数、最大线程数、线程存活时间等。可以在application.properties或application.yml中…

强化学习 - 基于策略搜索和策略优化: 高斯策略

最近在做毕设需要用强化学习来做控制&#xff0c;对强化学习的知识点做一下总结。 高斯策略 高斯策略属于强化学习中的基于策略优化的分支&#xff08;Policy Optimization&#xff09;&#xff0c;尤其是策略梯度方法&#xff08;Policy Gradient Methods&#xff09; 的一部…

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

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

论文阅读笔记: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…

MySQL篇之对MySQL进行参数优化,提高MySQL性能

1. MySQL参数优化说明 MySQL 参数调优是提高数据库性能的重要手段之一。通过调整 MySQL 的配置参数&#xff0c;可以优化查询速度、提升并发处理能力、减少资源消耗等。 MySQL 的性能优化涉及到多个方面&#xff0c;包括内存管理、磁盘 I/O、查询优化、连接管理、复制配置等。…

8621 二分查找

SCAU数据结构OJ第五章 文章目录 8621 二分查找 8621 二分查找 Description 编写Search_Bin函数&#xff0c;实现在一个递增有序数组ST中采用折半查找法确定元素位置的算法. 输入格式 第一行: 元素个数n 第二行&#xff1a;依次输入n个元素的值&#xff08;有序&#xff09; 第…

差分等长的原理

差分等长是指在设计差分信号传输线路时&#xff0c;保证两条差分线的长度尽量一致&#xff0c;长度之差在一个合理的范围内。这是为了确保两个差分信号时刻保持相反极性&#xff0c;减少共模分量&#xff0c;从而提高信号传输的质量。 在差分信号传输中&#xff0c;两条差分线…