美文网首页
【算法题】2572. 无平方子集计数

【算法题】2572. 无平方子集计数

作者: 程序员小2 | 来源:发表于2023-04-14 15:32 被阅读0次

    题目:

    给你一个正整数数组 nums 。

    如果数组 nums 的子集中的元素乘积是一个 无平方因子数 ,则认为该子集是一个 无平方 子集。

    无平方因子数 是无法被除 1 之外任何平方数整除的数字。

    返回数组 nums 中 无平方 且 非空 的子集数目。因为答案可能很大,返回对 109 + 7 取余的结果。

    nums 的 非空子集 是可以由删除 nums 中一些元素(可以不删除,但不能全部删除)得到的一个数组。如果构成两个子集时选择删除的下标不同,则认为这两个子集不同。

    示例 1:

    输入:nums = [3,4,4,5]
    输出:3
    解释:示例中有 3 个无平方子集:

    • 由第 0 个元素 [3] 组成的子集。其元素的乘积是 3 ,这是一个无平方因子数。
    • 由第 3 个元素 [5] 组成的子集。其元素的乘积是 5 ,这是一个无平方因子数。
    • 由第 0 个和第 3 个元素 [3,5] 组成的子集。其元素的乘积是 15 ,这是一个无平方因子数。
      可以证明给定数组中不存在超过 3 个无平方子集。
      示例 2:

    输入:nums = [1]
    输出:1
    解释:示例中有 1 个无平方子集:

    • 由第 0 个元素 [1] 组成的子集。其元素的乘积是 1 ,这是一个无平方因子数。
      可以证明给定数组中不存在超过 1 个无平方子集。

    提示:

    1 <= nums.length <= 1000
    1 <= nums[i] <= 30

    java代码:

    class Solution {
        private static final int[] PRIMES = new int[]{2, 3, 5, 7, 11, 13, 17, 19, 23, 29};
        private static final int MOD = (int) 1e9 + 7, MX = 30, N_PRIMES = PRIMES.length, M = 1 << N_PRIMES;
        private static final int[] SF_TO_MASK = new int[MX + 1]; // SF_TO_MASK[i] 为 i 的质因子集合(用二进制表示)
    
        static {
            for (int i = 2; i <= MX; ++i)
                for (int j = 0; j < N_PRIMES; ++j) {
                    int p = PRIMES[j];
                    if (i % p == 0) {
                        if (i % (p * p) == 0) { // 有平方因子
                            SF_TO_MASK[i] = -1;
                            break;
                        }
                        SF_TO_MASK[i] |= 1 << j; // 把 j 加到集合中
                    }
                }
        }
    
        public int squareFreeSubsets(int[] nums) {
            var f = new int[M]; // f[j] 表示恰好组成质数集合 j 的方案数
            f[0] = 1; // 质数集合是空集的方案数为 1
            for (int x : nums) {
                int mask = SF_TO_MASK[x];
                if (mask >= 0) // x 是 SF
                    for (int j = M - 1; j >= mask; --j)
                        if ((j | mask) == j)  // mask 是 j 的子集
                            f[j] = (f[j] + f[j ^ mask]) % MOD; // 不选 mask + 选 mask
            }
            var ans = 0L;
            for (int v : f) ans += v;
            return (int) ((ans - 1) % MOD); // -1 去掉空集(nums 的空子集)
        }
    }
    

    相关文章

      网友评论

          本文标题:【算法题】2572. 无平方子集计数

          本文链接:https://www.haomeiwen.com/subject/lkhtjdtx.html