【每日一题】1994.好子集的数目
1994.好子集的数目
- 题目描述
- 解决方案:状态压缩+动态规划
- 代码:Python
题目来源:LeetCode
原文链接:https://mp.weixin.qq.com/s/myI7_ZwJM7kizrwUtWgAZQ
难度级别:困难
题目描述
给你一个整数数组 nums。如果 nums 的一个子集中,所有元素的乘积可以表示为一个或多个 互不相同的质数 的乘积,那么我们称它为 好子集。
- 比方说,如果 nums = [1, 2, 3, 4] :
- [2, 3] ,[1, 2, 3] 和 [1, 3] 是 好 子集,乘积分别为 6 = 2 × 3 6 = 2 \times 3 6=2×3 , 6 = 2 × 3 6 = 2 \times 3 6=2×3 和 3 = 3 。
- [1, 4] 和 [4] 不是 好 子集,因为乘积分别为 4 = 2 × 2 4 = 2 \times 2 4=2×2 和 4 = 2 × 2 4 = 2 \times 2 4=2×2 。
请你返回 nums 中不同的 好 子集的数目对 1 0 9 + 7 10^9 + 7 109+7 取余 的结果。
nums 中的 子集 是通过删除 nums 中一些(可能一个都不删除,也可能全部都删除)元素后剩余元素组成的数组。如果两个子集删除的下标不同,那么它们被视为不同的子集。
示例1:
输入:nums = [1,2,3,4]
输出:6
解释:好子集为:
- [1,2]:乘积为 2 ,可以表示为质数 2 的乘积。
- [1,2,3]:乘积为 6 ,可以表示为互不相同的质数 2 和 3 的乘积。
- [1,3]:乘积为 3 ,可以表示为质数 3 的乘积。
- [2]:乘积为 2 ,可以表示为质数 2 的乘积。
- [2,3]:乘积为 6 ,可以表示为互不相同的质数 2 和 3 的乘积。
- [3]:乘积为 3 ,可以表示为质数 3 的乘积。
示例2:
输入:nums = [4,2,3,15]
输出:5
解释:好子集为:
- [2]:乘积为 2 ,可以表示为质数 2 的乘积。
- [2,3]:乘积为 6 ,可以表示为互不相同质数 2 和 3 的乘积。
- [2,15]:乘积为 30 ,可以表示为互不相同质数 2,3 和 5 的乘积。
- [3]:乘积为 3 ,可以表示为质数 3 的乘积。
- [15]:乘积为 15 ,可以表示为互不相同质数 3 和 5 的乘积。
提示:
- 1 < = n u m s . l e n g t h < = 1 0 5 1 <= nums.length <= 10^5 1<=nums.length<=105
- 1 < = n u m s [ i ] < = 30 1 <= nums[i] <= 30 1<=nums[i]<=30
解决方案:状态压缩+动态规划
题目乍看毫无头绪,但是仔细阅读之后,发现规定数组nums中的元素不超过30,因此可以将[1,30]中的整数分成如下三类:
- 对于任意一个好子集来说,添加任意数目的1,得到的新子集仍然是好子集;
- 2, 3, 5, 6, 7, 10, 11, 13, 14, 15, 17, 19, 21, 22, 23, 26, 29, 30:这些数均不包含平方因子,因此每个数在好子集中至多出现一次;
- 4, 8, 9, 12, 16, 18, 20, 24, 25, 27, 28:这些数包含平方因子,因此一定不能在好子集中出现。
首先,通过硬编码的方式把[1,30]中的整数按照上述分类,也可以先预处理出所有[1,30]中质数2, 3, 5, 7, 11, 13, 17, 19, 23, 29,再通过试除的方式动态分类。
分类完成后,就可以考虑使用动态规划了。由于每个质因数只能出现一次,并且[1, 30]中一共有10个质数,因此可以用一个长度为10的二进制数mask表示这些质因数的使用情况,其中mask的第 i 位为1,表示第 i 个质数已经被使用过了。
因此,定义 f [ i ] [ m a s k ] f[i][mask] f[i][mask]表示只选择[2,i]范围内的数,并且选择的数的质因数使用情况为mask时的方案数。
- 如果 i 本身包含平方因子,那么无法选择 i , 相当于在[2, i-1]范围内选择,状态转移方程为 f [ i ] [ m a s k ] = f [ i − 1 ] [ m a s k ] f[i][mask] = f[i-1][mask] f[i][mask]=f[i−1][mask]
- 如果 i 本身不包含平方因子,记其包含的质因子的二进制表示为subset(同样可以通过试除的方法得到),那么状态转移方程为 f [ i ] [ m a s k ] = f [ i − 1 ] [ m a s k ] + f [ i − 1 ] [ m a s k s u b s e t ] × f r e q [ i ] f[i][mask]=f[i-1][mask]+f[i-1][mask\\subset]\times freq[i] f[i][mask]=f[i−1][mask]+f[i−1][masksubset]×freq[i]其中:
- freq[i]表示数组nums中 i 出现的次数;
- mask\subset表示从二进制表示mask中去除所有在subset中出现的1,可以使用按位异或运算实现。这里需要保证subset是mask的子集,可以使用按位与运算来判断。
动态规划的边界条件为: f [ 1 ] [ 0 ] = 2 f r e q [ 1 ] f[1][0]=2freq[1] f[1][0]=2freq[1]即每一个在数组nums中出现的1都可以选或者不选。最终的答案即为所有 f [ 30 ] [ . . ] f[30][..] f[30][..]中除了 f [ 30 ] [ 0 ] f[30][0] f[30][0]以外的项的总和。
细节
注意到 f [ i ] [ m a s k ] f[i][mask] f[i][mask]只会从 f [ i − 1 ] [ . . ] f[i-1][..] f[i−1][..]转移而来,并且 f [ i − 1 ] [ . . ] f[i-1][..] f[i−1][..]中的下标总是小于mask,因此我们可以使用类似0-1背包的空间优化方法,在遍历mask时从 2 1 0 − 1 2^10-1 210−1到1逆序遍历,这样就只需要使用一个长度为 2 1 0 2^10 210的一维数组做状态转移了。
代码:Python
#!/usr/bin/env python
from collections import Counter
from typing import List# Hard level
class Solution:# 状态压缩动态规划def numberOfGoodSubsets(self, nums: List[int]) -> int:primes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]mod = 10 ** 9 + 7freq = Counter(nums)f = [0] * (1 << len(primes))f[0] = pow(2, freq[1], mod)for i, occ in freq.items():if i == 1:continue# 检查 i 的每个质因数是否均不超过 1 个subset, x = 0, icheck = Truefor j, prime in enumerate(primes):if x % (prime * prime) == 0:check = Falsebreakif x % prime == 0:subset |= (1 << j)if not check:continue# 动态规划for mask in range((1 << len(primes)) - 1, 0, -1):if (mask & subset) == subset:f[mask] = (f[mask] + f[mask ^ subset] * occ) % modans = sum(f[1:]) % modreturn ansif __name__ == '__main__':today = Solution()nums = list(map(int, input('nums = ').strip().split(',')))print(today.numberOfGoodSubsets(nums))
复杂度分析
- 时间复杂度: O ( n + C × O ( 2 π ( C ) ) O(n + C × O(2π(C)) O(n+C×O(2π(C))。其中 n 是数组 nums 的长度,C 是 nums 元素的最大值,在本题中 C = 30,π(x) 表示 ≤x 的质数的个数。
- 一共需要考虑 O ( C ) O(C) O(C)个数,每个数需要 O ( 2 π ( C ) ) O(2π(C)) O(2π(C))的时间计算动态规划;
- 在初始时需要遍历一遍所有的数,时间复杂度为 O ( n ) O(n) O(n)。
- 空间复杂度: O ( 2 π ( C ) ) O(2π(C)) O(2π(C)),即为动态规划需要使用的空间。
相关文章:
【每日一题】1994.好子集的数目
1994.好子集的数目 题目描述解决方案:状态压缩动态规划代码:Python 题目来源:LeetCode 原文链接:https://mp.weixin.qq.com/s/myI7_ZwJM7kizrwUtWgAZQ 难度级别:困难 题目描述 给你一个整数数组 nums。如果 nums 的一…...
坚持伙伴优先,共创数据存储新生态
4 月 26 日,2023 阿里云合作伙伴大会上,阿里巴巴集团董事会主席兼 CEO、阿里云智能集团 CEO 张勇表示,阿里云的核心定位是一家云计算产品公司,生态是阿里云的根基。让被集成说到做到的核心,是要坚定走向“产品被集成”…...
树形结构的三级分类如何实现?
概述: 本三级联动分类服务端使用的是: Springboot MyBatis-plus,前端使用的是:VueElementUI,树形控件使用的是el-tree。本三级联动分类可以把任一子项拖拽到其它目录,可以添加、编辑、删除分类。 效果图:…...
SSM整合完整流程
🏠个人主页:shark-Gao 🧑个人简介:大家好,我是shark-Gao,一个想要与大家共同进步的男人😉😉 🎉目前状况:23届毕业生,目前在某公司实习…...
虹科方案 | 助力高性能视频存储解决方案-2
上篇文章《虹科方案 | 助力高性能视频存储解决方案-1》我们分享了虹科&ATTO 和 Avid 共同创建协作解决方案,助力高性能视频存储,今天我们再深入介绍一下我们的案例详情。 一、行业挑战 从高端广播设施到小型独立工作室的媒体后期制作环境都需要允许多…...
java版深圳 工程管理系统软件 自主研发,工程行业适用 软件源码
Java版工程项目管理系统 Spring CloudSpring BootMybatisVueElementUI前后端分离 功能清单如下: 首页 工作台:待办工作、消息通知、预警信息,点击可进入相应的列表 项目进度图表:选择(总体或单个)项目显示…...
云原生Istio架构和组件介绍
目录 1 Istio 架构2 Istio组件介绍2.1 Pilot2.2 Mixer2.3 Citadel2.4 Galley2.5 Sidecar-injector2.6 Proxy(Envoy)2.7 Ingressgateway2.8 其他组件 1 Istio 架构 Istio的架构,分为控制平面和数据面平两部分。 - 数据平面:由一组智能代理([En…...
吹爆,全网第一个手把手教你从零开始搭建Spring Cloud Alibaba的笔记
Spring Cloud Alibaba 是阿里巴巴提供的微服务开发一站式解决方案,是阿里巴巴开源中间件与 Spring Cloud 体系的融合。 Springcloud 和 Srpingcloud Alibaba 区别? SpringCloud: 部分组件停止维护和更新,给开发带来不便;SpringCl…...
企业短信遭疯狂盗用,可能是没配置验证码
手机短信作为一种快捷的通讯方式被广泛应用。不仅在个人日常生活中,企业也习惯使用手机短信来进行验证和提醒,以保证业务的正常进行。随着数字化的发展,手机短信也成为了不法分子滥用的目标之一,给个人和企业带来不同经济损失。 个…...
【UE】直升机沿样条线移动
效果 步骤 1. 将虚幻商城中的免费资产导入工程 下载完毕后可以看到如下文件 2. 新建一个Actor蓝图类,命名为“Track”,这个蓝图就是用来画样条线的 打开“Track”,添加样条组件 3. 打开“BP_West_Heli_AH64D” 在事件图表中先新建一个时间轴…...
GaussDB_200_6.5.1部署安装
目录 安装前准备 安装依赖 修改/etc/hosts 上传解压介质 预安装 拷贝安装包 预安装配置 编辑preinstall.ini配置文件 编辑host0配置文件 执行预安装命令 安装FusionInsight_Manager 修改install安装配置文件 执行安装命令 web操作安装数据库 GaussDB200测试 配…...
软件工具 | Python调用运筹优化求解器(一):以CVRPVRPTW为例
目录 1. 引言2. 求解器介绍3. 基础语言3.1 创建模型3.2 添加变量3.3 添加目标函数3.4 添加约束3.5 设置参数3.6 求解 4. 数学模型4.1 [CVRP数学模型](https://mp.weixin.qq.com/s/DYh-5WkrYxk1gCKo8ZjvAw)4.2 [VRPTW数学模型](https://mp.weixin.qq.com/s/tF-ayzjpZfuZvelvItue…...
如何在JAVA中实现网络编程?
在Java中实现网络编程通常需要使用Java提供的网络编程库——Java Networking API。Java Networking API支持常见的TCP和UDP协议,包括Socket、ServerSocket、DatagramSocket等类,通过这些类,我们可以创建、连接、监听和传输数据。 下面是在Ja…...
【redis】redis的缓存过期淘汰策略
【redis】redis的缓存过期淘汰策略 文章目录 【redis】redis的缓存过期淘汰策略前言一、面试题二、redis内存满了怎么办?1、redis默认内存是多少?在哪查看?如何修改?在conf配置文件中可以查看 修改,内存默认是0redis的默认内存有…...
ASP.NET动态Web开发技术第8章
第8章ASP.NET数据访问 一.预习笔记 1.SqlDataSource控件 SqlDataSource数据源控件支持连接SQL关系数据库,它使用SQL命令来检索和修改数据。通常将SqlDataSource数据源控件与数据绑定控件一起使用。 属性1:ID:当前数据源控件的唯一标识符 …...
【旋转编码器如何工作以及如何将其与Arduino一起使用】
在本教程中,我们将学习旋转编码器的工作原理以及如何将其与Arduino一起使用。您可以观看以下视频或阅读下面的书面教程。 1. 概述 旋转编码器是一种位置传感器,用于确定旋转轴的角度位置。它根据旋转运动产生模拟或数字电信号。 有许多不同类型的旋转编码器按输出信号或传感…...
Tre靶场通关过程(linpeas使用+启动项编辑器提权)
Tre靶场通关 通过信息收集获得到了普通用户账号密码,利用PEASS-ng的linpeas脚本进行提权的信息收集,根据已有信息进行提权。 靶机下载地址: https://download.vulnhub.com/tre/Tre.zip 信息收集 靶机IP探测:192.168.0.129 a…...
java多线程下
ThreadLocal ThreadLocal 有什么用?通常情况下,我们创建的变量是可以被任何一个线程访问并修改的。如果想实现每一个线程都有自己的专属本地变量该如何解决呢?JDK 中自带的ThreadLocal类正是为了解决这样的问题。 ThreadLocal类主要解决的就…...
使用无标注的数据训练Bert
文章目录 1、准备用于训练的数据集2、处理数据集3、克隆代码4、运行代码5、将ckpt模型转为bin模型使其可在pytorch中运用 Bert官方仓库:https://github.com/google-research/bert 1、准备用于训练的数据集 此处准备的是BBC news的数据集,下载链接&…...
《Netty》从零开始学netty源码(五十二)之PoolThreadCache
PoolThreadCache Netty有一个大的公共内存容器PoolArena,用来管理从操作系统中获得的内存,在高并发下如果所有线程都去这个大容器获取内存它的压力是非常大的,所以Netty为每个线程建立了一个本地缓存,即PoolThreadCacheÿ…...
放弃40k月薪的程序员工作,选择公务员,我来分享一下看法
我有一个朋友,拒绝了我为他提供的4万薪水的工作,去了一个体制内的银行,做程序员,即使薪水减半。他之前在北京一家大公司做程序员,一个月30k。当我开始创业时,我拉他来和我一起干,但那时我们太小…...
【MybatisPlus】高级版可视化、可配置 自动生成代码
今天看别人使用了一个更加智能的生成代码工具,可视化、可配置策略,非常方便,配置一次,在哪都可以使用,也不会跟项目藕合下面简单说一下使用方式。 1、介绍mybatis-plus-generator-ui 主要是封装了mybatis-plus-gener…...
【图像分割】【深度学习】Windows10下f-BRS官方代码Pytorch实现
【图像分割】【深度学习】Windows10下f-BRS官方代码Pytorch实现 提示:最近开始在【图像分割】方面进行研究,记录相关知识点,分享学习中遇到的问题已经解决的方法。 文章目录 【图像分割】【深度学习】Windows10下f-BRS官方代码Pytorch实现前言f-BRS模型运行环境安装1.下载源码并…...
2023/5/4总结
刷题: 第二周任务 - Virtual Judge (vjudge.net) 这一题用到了素筛,然后穷举即可 #include<stdio.h> #define Maxsize 500000 int a[Maxsize]; long long b[Maxsize]; long long max0; int sushu() {a[0]a[1]0;int i,j,k;for(i2,k0;i<Maxsize;i){if(a[i…...
electron+vue3全家桶+vite项目搭建【17】pinia状态持久化
文章目录 引入问题演示实现效果展示、实现步骤1.封装状态初始化函数2.封装状态更新同步函数3.完整代码 引入 上一篇文章我们已经实现了electron多窗口中,pinia的状态同步,但你会发现,如果我们在一个窗口里面修改了状态,然后再打开…...
java基础入门-05-【面向对象进阶(static继承)】
Java基础入门-05-【面向对象进阶(static&继承)】 13、面向对象进阶(static&继承)1.1 如何定义类1.2 如何通过类创建对象1.3 封装1.3.1 封装的步骤1.3.2 封装的步骤实现 1.4 构造方法1.4.1 构造方法的作用1.4.2 构造方法的…...
day12 IP协议与ethernet协议
目录 IP包头 IP网的意义 IP数据报的格式 IP数据报分片 以太网包头(链路层协议) IP包头 IP网的意义 当互联网上的主机进行通信时,就好像在一个网络上通信一样,看不见互联的各具体的网络异构细节; 如果在这种覆盖…...
蓝牙耳机哪款性价比高?2023蓝牙耳机性价比排行
随着蓝牙耳机的使用愈发频繁,蓝牙耳机产品也越来越多,蓝牙耳机的功能、价格、外观设计等都不尽相同。接下来,我来给大家推荐几款性价比高的蓝牙耳机,感兴趣的朋友一起来看看吧。 一、南卡小音舱Lite2蓝牙耳机 参考价:…...
关于C语言的一些笔记
文章目录 May4,2023常量问题基本数据类型补码printf的字符格式控制关于异或、异或的理解赋值运算i和i的区别关系运算符 May5,2023逻辑运算中‘非’的理解逗号运算运算符的优先级问题三目运算 摘自加工于C技能树 May4,2023 常量问题 //定义常量 const float PI; PI…...
【Python入门知识】NumPy数组迭代及连接
前言 嗨喽~大家好呀,这里是魔王呐 ❤ ~! 数组迭代 迭代意味着逐一遍历元素,当我们在 numpy 中处理多维数组时, 可以使用 python 的基本 for 循环来完成此操作。 如果我们对 1-D 数组进行迭代,它将逐一遍历每个元素。 实例 迭…...
网站制作公司多少人/郑州做网站最好的公司
需求: 从网上下载的N张.png图片保存到image目录中,将下载下来的图片全部重命名test1.png/test2.png... 实现代码: 目录结构: config-->setting.py #!/usr/bin/env python # -*- coding: utf-8 -*- __author__ tian __data__ …...
怎么在网站做外部链接/定制网站建设推广服务
微信扫码关注公众号 :前端前端大前端,追求更精致的阅读体验 ,一起来学习啊关注后发送关键资料,免费获取一整套前端系统学习资料和老男孩python系列课程 学习资源推荐 区分进程和线程 进程是cpu资源分配的最小单位,可独立运行线程是cpu调度…...
郑州区块链数字钱包网站开发过程/一键制作免费网站的app
面向对象的特征 封装、继承、多态(、抽象) 封装 将某些逻辑或者是代码提取成某种对应的形式,这个提取的过程就是封装 封装包括:方法的封装、类的封装以及访问权限的封装。 访问权限设置主要体现为---将属性设置为私有的࿰…...
wordpress stheme/免费的个人网页
1.先搞清微信小程序的生命周期和页面生命周期的关系 微信小程序的生命周期包括App生命周期和页面生命周期。App生命周期指的是小程序从启动到退出的整个过程,而页面生命周期则是指小程序中每个页面从创建到销毁的过程。 在小程序中,当用户打开小程序时&a…...
个人网站需要买服务器吗/个人网站制作源代码
最近使用mediaelementjs做一个iPad上的Html5的video标签的播放器包装. 首先感谢一下mediaelementjs这样的开源项目, 可用度极高, 代码质量明显比我自己写要好多了, 模块化清晰, 许可证很开放(MIT). 开发的过程中遇到了些浏览器兼容问题, 也涉及到一下iPad这样的平板平板设备上…...
电脑课做网站所需的软件/自己怎么做网站
前言: 在使用gitLab中时遇到一个问题,就是我在gitLab新建分支后,在本地切换分支不成功,遇到了这个问题,在大佬的博客的指点下,顺利解决这个问题,记录下我一步一步解决问题的过程,最后…...