题目
类型:位运算
解题思路
代码
class Solution {int MOD = (int)1e9+7;int[] p = new int[]{2, 3, 5, 7, 11, 13, 17, 19, 23, 29};int[] cnts = new int[35];public int numberOfGoodSubsets(int[] nums) {int n = nums.length;for (int i : nums) cnts[i]++;int mask = 1 << 10;long[] f = new long[mask];f[0] = 1;for (int i = 2; i <= 30; i++) {if (cnts[i] == 0) continue;// 对 i 进行试除int cur = 0, x = i;boolean ok = true;for (int j = 0; j < 10; j++) {int t = p[j], c = 0;while (x % t == 0) {cur |= (1 << j);x /= t; c++;}// 如果 i 能够被同一质数试除多次,说明 i 不能加到子集,跳过if (c > 1) {ok = false;break;}}if (!ok) continue;// 枚举前一状态 prev//(确保考虑一个新数值 i 时,依赖的子集 prev 存储的为尚未考虑 i 的方案数)for (int prev = mask - 1; prev >= 0; prev--) {// 只有当前选择数与前一状态不冲突,则能够进行转移,将方案数进行累加if ((prev & cur) != 0) continue;f[prev | cur] = (f[prev | cur] + f[prev] * cnts[i]) % MOD;}}long ans = 0;// 统计所有非空集的方案数for (int i = 1; i < mask; i++) ans = (ans + f[i]) % MOD;// 在此基础上,考虑每个 1 选择与否对答案的影响for (int i = 0; i < cnts[1]; i++) ans = ans * 2 % MOD;return (int) ans;}}
