The Number of Good Subsets

The Number of Good Subsets

You are given an integer array nums . We call a subset of nums good if its product can be represented as a product of one or more distinct prime numbers.

  • For example, if nums = [1, 2, 3, 4] :
    • [2,3] ,  [1, 2, 3] , and [1, 3] are good subsets with products 6 = 2*3 , 6 = 2*3 , and 3 = 3 respectively.
    • [1, 4] and [4] are not good subsets with products 4 = 2*2 and 4 = 2*2 respectively.

Return the number of different good subsets in nums modulo 109+7.

A subset of nums is any array that can be obtained by deleting some (possibly none or all) elements from nums . Two subsets are different if and only if the chosen indices to delete are different.

Example 1:

复制代码
Input: nums = [1,2,3,4]
Output: 6
Explanation: The good subsets are:
- [1,2]: product is 2, which is the product of distinct prime 2.
- [1,2,3]: product is 6, which is the product of distinct primes 2 and 3.
- [1,3]: product is 3, which is the product of distinct prime 3.
- [2]: product is 2, which is the product of distinct prime 2.
- [2,3]: product is 6, which is the product of distinct primes 2 and 3.
- [3]: product is 3, which is the product of distinct prime 3.
复制代码

Example 2:

Input: nums = [4,2,3,15]
Output: 5
Explanation: The good subsets are:
- [2]: product is 2, which is the product of distinct prime 2.
- [2,3]: product is 6, which is the product of distinct primes 2 and 3.
- [2,15]: product is 30, which is the product of distinct primes 2, 3, and 5.
- [3]: product is 3, which is the product of distinct prime 3.
- [15]: product is 15, which is the product of distinct primes 3 and 5.

Constraints:

1nums.length105
1nums[i]30

 

解题思路

  Count the Number of Square-Free Subsets的扩展版,n扩大到了105,当然题意也有些变化(港真lc直接把原题搬到周赛这样做真的好吗)。如果还是像这题一样的做法,由于时间复杂度为O(n210),那么一定会超时。

  注意,由于每个数最大不超过30,因此我们可以把值域定义为状态,而不是把下标定义为状态。

  定义状态f(i,j)表示从数值2i中选择,乘积结果的状态为j(即包含了哪些质数)的所有方案的个数。其中根据数值i选或不选来划分状态。状态转移方程为f(i,j)=f(i1,j)+f(i1,jsti)×cnti     (保证j & sti=sti)

  其中cnti表示数值i出现的次数(显然一个合法的结果的乘积只能乘一次i,一次有多少个i就有多少种方案)。如果i本身就不合法(即某个质因子次数超过1),那么很明显该数是不能选择的。为了方便这里把不合法的数的cnti定义为0,那么同样适用上面的状态转移方程。

  为什么要从2开始呢?1的情况呢?该题的要求是“所有元素的乘积可以表示为一个或多个互不相同的质数的乘积”,而1不是质数,因此乘积的结果不能是1,但可以用1去乘其他的数。我们把1归为状态0,显然f(1,0)=2cnt1,其他的i (2i30)可以从f(1,0)转移过来。

  最后的答案就是i=12101f(30,i)i不从0开始是为了不统计乘积结果为1的情况。

  AC代码如下,时间复杂度为O(30210)

复制代码
 1 class Solution {
 2 public:
 3     int mod = 1e9 + 7;
 4     
 5     int numberOfGoodSubsets(vector<int>& nums) {
 6         int primes[10] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29};
 7         vector<int> cnt(31), st(31);
 8         for (auto &x : nums) {
 9             bool flag = true;
10             int t = x;
11             for (int i = 0; i < 10; i++) {
12                 int p = primes[i];
13                 if (t % p == 0) {
14                     int s = 0;
15                     st[x] |= 1 << i;
16                     while (t % p == 0) {
17                         s++;
18                         t /= p;
19                     }
20                     if (s > 1) {
21                         flag = false;
22                         break;
23                     }
24                 }
25             }
26             if (flag) cnt[x]++;
27         }
28         vector<vector<int>> f(31, vector<int>(1 << 10));
29         f[1][0] = 1;
30         while (cnt[1]--) {
31             f[1][0] = f[1][0] * 2 % mod;
32         }
33         for (int i = 2; i <= 30; i++) {
34             for (int j = 0; j < 1 << 10; j++) {
35                 f[i][j] = f[i - 1][j];
36                 if ((j & st[i]) == st[i]) f[i][j] = (f[i][j] + 1ll* f[i - 1][j ^ st[i]] * cnt[i]) % mod;
37             }
38         }
39         int ret = 0;
40         for (int i = 1; i < 1 << 10; i++) {
41             ret = (ret + f[30][i]) % mod;
42         }
43         return ret;
44     }
45 };
复制代码

 

参考资料

  好子集的数目:https://leetcode.cn/problems/the-number-of-good-subsets/solution/hao-zi-ji-de-shu-mu-by-leetcode-solution-ky65/

posted @   onlyblues  阅读(52)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
历史上的今天:
2022-02-19 波动数列
Web Analytics
点击右上角即可分享
微信分享提示