质因数分解(cpp实现)--一种快速求得一个数有多少个因子的黑魔法

前言

最近机试没少吃不会质因数分解的亏,用传统的求得因子个数只能过一点点…(ex, 20%)
质因数分解后,可以将因子问题转化为 集合的组合问题,因此会很快,目测是 l o g n log n logn (n是该整数的值)。



传统解法

假设输入整数的数值是n, 那么时间复杂度就是 n \sqrt{n} n , 显然数字很大时不能接受…

// 朴素方法  sqrt(n)
int calFactorNUmSimple(int num) {
    unordered_map<int, int> umap;
    umap[1] = 1;
    umap[num] = 1;
    for (int i = 2; i * i <= num; i++) {
        if (num % i == 0) {
            umap[i] = 1;
            umap[num / i] = 1;
        }
    }
    cout << "(simple)factor num: " <<  umap.size() << endl;
    // for (auto it: umap)
    //     cout << it.first << " ";
    // cout << endl;

    return umap.size();
}

多嘴一句,如果不想输出因子是啥,也不用开一个map, 直接用一个变量存一下个数就行。

int calFactorNUmSimpleJustForNum(int num) {
    int res = 2;
    for (int i = 2; i * i <= num; i++) {
        if (num % i == 0) {
            res++;
            if (i != num / i)
                res++;
        }
    }
    cout << "(simple)factor num: " <<  res << endl;
    return res;
}



质因数分解算法

没有仔细求证,目测 O ( l o g n ) O(log n) O(logn) 的时间复杂度。
该算法核心是 将一个数分成一个个质因数集合,每个值为 i 集合可以选出来 0到 umap[i] 个元素
因此构成的因子种类或者说个数就是 每个集合的个数 + 1 后 再相乘了
比如 108 = 2 2 ∗ 3 3 108 = 2^2 * 3 ^3 108=2233, 这个例子中 我们把 108 分成 两个质因数 2 和 3 的集合,他们分别有2个元素和3个元素,
那么总的因子种类就是 我们可以在 2 的集合中取 0 个(0个就是2的0次方就是1)或 1个,2个;
同理,从3的质因数集合中可以取 0个,1个, 2个,3个; 那么最终因数种类就是 ( 2 + 1 ) ( 3 + 1 ) = 12 (2+1) (3+1) = 12 (2+1)(3+1)=12

具体地,我们从 2的质因数集合中取 1个,从3的质因数集合中取2个,那么当前的因子就是 2 1 × 3 2 = 18 2^1 \times 3^2 = 18 21×32=18

int calFactorNum(int num) {
    unordered_map<int, int> umap; 
    int x = num;
    for (int i = 2; i * i <= x; i++) {
        while (x % i == 0) {
            x /= i;
            umap[i]++;
        }
    }
    if (x > 1)  // 没除完,那么 x 本身也是一个质数
        umap[x]++;

    // 一个数分成一个个质因数集合,每个值为 i 集合可以选出来 0到umap[i]个元素
    // 因此构成的因子种类/个数就是  每个集合的个数 + 1 后 再相乘了
    int res = 1;
    for (auto it: umap) {
        // cout << "val: " << it.first << ", exp: " << it.second << endl;
        res *= (it.second + 1);
    }
    cout << "factor num:" << res << endl;
    return res;
}



lc 2521

2521. 数组乘积中的不同质因数数目
可以练练手

class Solution {
public:
    int distinctPrimeFactors(vector<int>& nums) {
        unordered_map<int, int> umap;
        for(auto x: nums) {
            // 每个数都来一次质因数分解
            for (int i = 2; i * i <= x; i++) {
                while(x % i == 0) {
                    umap[i]++;
                    x /= i;
                }
            }
            if (x > 1)
                umap[x]++;
        }
        return umap.size();
    }
};



demo完整代码

本案例完整代码 (C++11以上标准即可运行)

//分解质因子 
#include <iostream>
#include <unordered_map>
using namespace std;


// 输出一下质因数分解
void tryOutputPrimeFactor(int num) {
    cout << num << "=";
    int x = num;
    for (int i = 2; i <= x; i++) { //循环查找判断质因数
        while (x % i == 0) { //若i为num的质因数,则输出i
            cout << i;
            x /= i;    //对num除以i后的数求取质因数
            if (x != 1)//判断num是否除尽 
                cout << "*";
        }
    }
    cout << endl;
}


// 朴素方法  sqrt(n)
int calFactorNUmSimple(int num) {
    unordered_map<int, int> umap;
    umap[1] = 1;
    umap[num] = 1;
    for (int i = 2; i * i <= num; i++) {
        if (num % i == 0) {
            umap[i] = 1;
            umap[num / i] = 1;
        }
    }
    cout << "(simple)factor num: " <<  umap.size() << endl;
    // for (auto it: umap)
    //     cout << it.first << " ";
    // cout << endl;

    return umap.size();
}


int calFactorNUmSimpleJustForNum(int num) {
    int res = 2;
    for (int i = 2; i * i <= num; i++) {
        if (num % i == 0) {
            res++;
            if (i != num / i)
                res++;
        }
    }
    cout << "(simple)factor num: " <<  res << endl;
    return res;
}


int calFactorNum(int num) {
    unordered_map<int, int> umap; 
    int x = num;
    for (int i = 2; i * i <= x; i++) {
        while (x % i == 0) {
            x /= i;
            umap[i]++;
        }
    }
    if (x > 1)  // 没除完,那么 x 本身也是一个质数
        umap[x]++;

    // 一个数分成一个个质因数集合,每个值为 i 集合可以选出来 0到umap[i]个元素
    // 因此构成的因子种类/个数就是  每个集合的个数 + 1 后 再相乘了
    int res = 1;
    for (auto it: umap) {
        // cout << "val: " << it.first << ", exp: " << it.second << endl;
        res *= (it.second + 1);
    }
    cout << "factor num:" << res << endl;
    return res;
}


int main()
{
    int num = 108;
    // calFactorNUmSimple(num);
    calFactorNUmSimpleJustForNum(num);
    calFactorNum(num);
    return 0;
}

output:

(simple)factor num: 12
factor num:12

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于OpenCv的图像特征点检测

⚠申明&#xff1a; 未经许可&#xff0c;禁止以任何形式转载&#xff0c;若要引用&#xff0c;请标注链接地址。 全文共计3077字&#xff0c;阅读大概需要3分钟 &#x1f308;更多学习内容&#xff0c; 欢迎&#x1f44f;关注&#x1f440;【文末】我的个人微信公众号&#xf…

从0开始linux(1)——文件操作

欢迎来到博主的专栏——从0开始linux 博主ID&#xff1a;代码小豪 博主使用的linux发行版是&#xff1a;CentOS 7.6 不同版本下的操作可能存在差异 文章目录 命令文件操作命令文件树和文件路径文件树绝对路径相对路径 文件属性tree指令删除文件复制文件 大家还记得在小学第一次…

C语言-链表实现贪吃蛇控制台游戏

使用C语言和链表实现贪吃蛇游戏 一、引言 贪吃蛇游戏是一个经典的游戏&#xff0c;它的玩法简单而富有挑战性。在这个博客中&#xff0c;我将分享如何使用C语言和链表数据结构来自主实现贪吃蛇游戏。我会详细介绍游戏的设计思路、编码过程、遇到的问题及解决方案&#xff0c;…

将要上市的自动驾驶新书《自动驾驶系统开发》中摘录各章片段 1

以下摘录一些章节片段&#xff1a; 1. 概论 自动驾驶系统的认知中有一些模糊的地方&#xff0c;比如自动驾驶系统如何定义的问题&#xff0c;自动驾驶的研发为什么会有那么多的子模块&#xff0c;怎么才算自动驾驶落地等等。本章想先给读者一个概括介绍&#xff0c;了解自动驾…

Rust 生命周期浅谈

1. 简述 Rust 中的每一个引用都有其 生命周期&#xff08;lifetime&#xff09;&#xff0c;也就是引用保持有效的作用域。大部分时候生命周期是隐含并可以推断的&#xff0c;正如大部分时候类型也是可以推断的一样。类似于当因为有多种可能类型的时候必须注明类型&#xff0c;…

JAVA语言开发的智慧城管系统源码:技术架构Vue+后端框架Spring boot+数据库MySQL

通过综合应用计算机技术、网络技术、现代通信技术等多种信息技术&#xff0c;充分融合RS遥感技术、GPS全球定位技术、GIS地理信息系统&#xff0c;开始建设一个动态可视的、实时更新的、精细量化的城市管理系统。智慧城管将采用云平台架构方式进行建设&#xff0c;基于现有数字…

【idea-sprongboot项目】SSH连接云服务器进行远程开发

继上一篇博客【阿里云服务器】ubuntu 22.04.1安装docker以及部署java环境-CSDN博客 目录 五、远程开发方式 1&#xff09;SSH进行远程开发 步骤 配置文件同步 window电脑远程操控 正式通过window电脑远程操控 运行在linux服务器上的远程程序 调试在linux服务器上的远程程…

恶补《操作系统》5_2——王道学习笔记

5.2_1 I-O核心子系统 1、用户层软件 假脱机系统 2、设备独立性软件&#xff08;设备无关性软件&#xff09; IO调度、设备保护、设备分配与回收、缓冲区管理 3、设备驱动程序&#xff08;比如打印机驱动&#xff09; 4、中断处理程序 5、硬件 5.2_2 假脱机技术&#xff…

PHP医疗不良事件上报系统源码 AEMS开发工具vscode+ laravel8 医院安全(不良)事件报告系统源码 可提供演示

PHP医疗不良事件上报系统源码 AEMS开发工具vscode laravel8 医院安全&#xff08;不良&#xff09;事件报告系统源码 可提供演示 医院安全不良事件报告系统&#xff08;AEMS&#xff09;&#xff1b;分为外部报告系统和内部报告系统两类。内部报告系统主要以个人为报告单位&…

智慧文旅开启沉浸式文化体验,科技让旅行更生动:借助智慧技术,打造沉浸式文化体验场景,让旅行者在旅行中深度感受文化的魅力

一、引言 随着科技的飞速发展&#xff0c;传统旅游行业正经历着前所未有的变革。智慧文旅&#xff0c;作为一种新兴的旅游模式&#xff0c;正以其独特的魅力&#xff0c;吸引着越来越多的旅行者。智慧文旅不仅改变了人们的旅行方式&#xff0c;更在深度上丰富了人们的文化体验…

linux上如何排查JVM内存过高?

怎么排查JVM内存过高&#xff1f; 前言&#xff1a; 想必工作一两年以后的同学都会逐渐面临到&#xff0c;jvm等问题&#xff0c;但是可能苦于无法熟练的使用一些工具&#xff1b;本文将介绍几个比较常用分析工具的使用方法&#xff0c;带着大家一步步定位分析问题。 1、top 查…

代码随想录算法训练营DAY54|C++动态规划Part15|647.回文子串、516最长回文子序列、

文章目录 647.回文子串思路CPP代码双指针 516最长回文子序列思路CPP代码 动态规划总结篇 647.回文子串 力扣题目链接 文章链接&#xff1a;647.回文子串 视频链接&#xff1a;动态规划&#xff0c;字符串性质决定了DP数组的定义 | LeetCode&#xff1a;647.回文子串 其实子串问…

【C++第八课 - string的底层实现】

目录 基础知识string构造函数和析构函数的坑构造函数析构函数 迭代器、范围for运算符重载operator [] const增删查改push_backreserveappendinserteraseswapfindsubstr拷贝构造 流插入和流提取<<流插入>>流提取clear 深浅拷贝传统写法现代写法 赋值传统写法现代写法…

## 01深度学习介绍与安装PyTorch

文章目录 深度学习的发展历史和基本概念早期历史兴起与发展基本概念 如何安装和设置PyTorch环境系统要求安装步骤验证安装 结语 深度学习的发展历史和基本概念 深度学习&#xff0c;一种通过使用具有多层结构的神经网络来学习数据的复杂模型的机器学习技术&#xff0c;近年来已…

[Java EE] 多线程(七): 锁策略

&#x1f338;个人主页:https://blog.csdn.net/2301_80050796?spm1000.2115.3001.5343 &#x1f3f5;️热门专栏:&#x1f355; Collection与数据结构 (90平均质量分)https://blog.csdn.net/2301_80050796/category_12621348.html?spm1001.2014.3001.5482 &#x1f9c0;Java …

奇偶校验码

目录 前言 校验原理简介 奇偶校验码 前言 在前两个文章的学习中,我们已经知道了数字字符这些简单的数据应该怎么在计算机内部进行表示,其实本质上是0101的二进制代码,但是这些数据在计算机内部进行计算存取和传送的过程中,由于计算机原器件可能会发生故障,也有可能因为某些…

python:set(集合)

set(集合) 去重处理&#xff0c;内容无序 列表使用&#xff1a;[] 元组使用&#xff1a;() 字符串使用&#xff1a;"" 集合使用&#xff1a;{} 基本语法; # 定义字面量集合&#xff1a;{元素&#xff0c;元素&#xff0c;元素&#xff0c;.......} 定义集合变…

【C语言】项目实践-贪吃蛇小游戏(Windows环境的控制台下)

一.游戏要实现基本的功能&#xff1a; • 贪吃蛇地图绘制 • 蛇吃食物的功能 &#xff08;上、下、左、右方向键控制蛇的动作&#xff09; • 蛇撞墙死亡 • 蛇撞自身死亡 • 计算得分 • 蛇身加速、减速 • 暂停游戏 二.技术要点 C语言函数、枚举、结构体、动态内存管…

用队列实现栈——leetcode刷题

题目的要求是用两个队列实现栈&#xff0c;首先我们要考虑队列的特点&#xff1a;先入先出&#xff0c;栈的特点&#xff1a;后入先出&#xff0c;所以我们的目标就是如何让先入栈的成员后出栈&#xff0c;后入栈的成员先出栈。 因为有两个队列&#xff0c;于是我们可以这样想&…

支付宝支付流程

第一步前端&#xff1a;点击去结算&#xff0c;前端将商品的信息传递给后端&#xff0c;后端返回一个商品的订单号给到前端&#xff0c;前端将商品的订单号进行存储。 对应的前端代码&#xff1a;然后再跳转到支付页面 // 第一步 点击去结算 然后生成一个订单号 // 将选中的商…