Count the Number of Square-Free Subsets
Count the Number of Square-Free Subsets
You are given a positive integer 0-indexed array nums .
A subset of the array nums is square-free if the product of its elements is a square-free integer.
A square-free integer is an integer that is divisible by no square number other than .
Return the number of square-free non-empty subsets of the array nums. Since the answer may be too large, return it modulo .
A non-empty subset of nums is an array that can be obtained by deleting some (possibly none but not all) elements from nums . Two subsets are different if and only if the chosen indices to delete are different.
Example 1:
Input: nums = [3,4,4,5] Output: 3 Explanation: There are 3 square-free subsets in this example: - The subset consisting of the 0th element [3]. The product of its elements is 3, which is a square-free integer. - The subset consisting of the 3rd element [5]. The product of its elements is 5, which is a square-free integer. - The subset consisting of 0th and 3rd elements [3,5]. The product of its elements is 15, which is a square-free integer. It can be proven that there are no more than 3 square-free subsets in the given array.
Example 2:
Input: nums = [1] Output: 1 Explanation: There is 1 square-free subset in this example: - The subset consisting of the 0th element [1]. The product of its elements is 1, which is a square-free integer. It can be proven that there is no more than 1 square-free subset in the given array.
Constraints:
解题思路
首先一个数是所谓的“无平方因子数”等价于该数的质因数分解中每一个质因子的次数恰好是。因此如果一个数的某个质因子的出现次数超过,那么该数一定不是“无平方因子数”,与该数相乘得到的数明显也不是。
因此我们先把所有质因子次数恰好为的数先筛出来,得到数组,然后再从中选择若干个数进行乘积,使得乘积结果的每个质因子的次数也要恰好为,那么这就是一个合法的子集。注意到相乘的结果本质就是选择若干个均不同的质因子进行乘积。
由于每个数最大不超过,而以内的质数只有个,因此可以考虑状压dp,状态一共有个二进制位,如果状态的某位是意味着相乘的结果包含该位所对应的质数。
定义状态表示从前个数中选,乘积结果的状态为(即包含了哪些质数)的所有方案的个数。根据第个数是否选择来进行状态划分。设表示第个数所包含的质因子的状态,状态转移方程为
其中如果,那么有选或不选这两种状态,因此。而如果定义,那么上面那条状态转移方程同样适用,因为,因此。
AC代码如下,时间复杂度为:
1 class Solution { 2 public: 3 int mod = 1e9 + 7; 4 5 int squareFreeSubsets(vector<int>& nums) { 6 int primes[10] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29}; // 30以内的质数 7 vector<int> a, st(31); 8 for (auto &x : nums) { // 对每个数进行质因数分解 9 bool flag = true; // 该数的每个质因子的次数是否均为1 10 int t = x; 11 for (int i = 0; i < 10; i++) { 12 int p = primes[i]; 13 if (t % p == 0) { 14 int cnt = 0; 15 st[x] |= 1 << i; 16 while (t % p == 0) { 17 cnt++; 18 t /= p; 19 } 20 if (cnt > 1) { // 质因子p的次数超过1个 21 flag = false; 22 break; 23 } 24 } 25 } 26 if (flag) a.push_back(x); // 筛出合法的数 27 } 28 int n = a.size(); 29 vector<vector<int>> f(n + 1, vector<int>(1 << 10)); 30 f[0][0] = 1; 31 for (int i = 1; i <= n; i++) { 32 for (int j = 0; j < 1 << 10; j++) { 33 f[i][j] = f[i - 1][j]; 34 int t = st[a[i - 1]]; 35 if ((j & t) == t) f[i][j] = (f[i][j] + f[i - 1][j ^ t]) % mod; // 如果要选择第i个数,那么j所表示的状态要包含第i个数的状态 36 } 37 } 38 int ret = 0; 39 for (int i = 0; i < 1 << 10; i++) { // 状态0表示空集和选择1的方案数 40 ret = (ret + f[n][i]) % mod; 41 } 42 return (ret - 1 + mod) % mod; // -1是除去空集的情况 43 } 44 };
参考资料
状压 DP:https://leetcode.cn/problems/count-the-number-of-square-free-subsets/solution/zhuang-ya-dp-by-tsreaper-dwts/
本文来自博客园,作者:onlyblues,转载请注明原文链接:https://www.cnblogs.com/onlyblues/p/17135345.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
2022-02-19 波动数列