跳到主要内容

1994.好子集的数目

链接:1994.好子集的数目
难度:Hard
标签:位运算、数组、数学、动态规划、状态压缩
简介:请你返回 nums 中不同的 好 子集的数目对 109 + 7 取余 的结果。

题解 1 - cpp

  • 编辑时间:2022-02-22
  • 执行用时:220ms
  • 内存消耗:179.2MB
  • 编程语言:cpp
  • 解法介绍:dfs 遍历,对于所有可重合因子进行遍历,可在每个方案中增加 1 的可能性,每个方案都可以选择任意一个 1 或者不选择,总可能性为 pow(2, cnt1)。
int mod = 1e9 + 7;
#define MAX 40
unordered_map<int, int> m = {
{23, 0b00000000010000000000000000000000},
{19, 0b00000000000001000000000000000000},
{17, 0b00000000000000010000000000000000},
{15, 0b00000000000000000000000000010100},
{14, 0b00000000000000000000000001000010},
{13, 0b00000000000000000001000000000000},
{30, 0b00000000000000000000000000010110},
{11, 0b00000000000000000000010000000000},
{29, 0b00010000000000000000000000000000},
{10, 0b00000000000000000000000000010010},
{26, 0b00000000000000000001000000000010},
{7, 0b00000000000000000000000001000000},
{6, 0b00000000000000000000000000000110},
{5, 0b00000000000000000000000000010000},
{22, 0b00000000000000000000010000000010},
{3, 0b00000000000000000000000000000100},
{21, 0b00000000000000000000000001000100},
{2, 0b00000000000000000000000000000010},
{1, 0b00000000000000000000000000000001},
};
int mod = 1e9 + 7;
#define MAX 40
class Solution {
public:
int arr[MAX] = {0}, num1;
int numberOfGoodSubsets(vector<int> &nums) {
for (auto &num : nums) {
if (m.count(num)) arr[num]++;
}
num1 = qpow(2, arr[1]);
long long ans = 0;
for (int num = 2; num < MAX; num++) {
if (arr[num]) dfs(ans, num, m[num], arr[num]);
}
return ans % mod;
}
void dfs(long long &ans, int num, int bits, long long sum) {
ans = (ans + sum * num1) % mod;
for (int nnum = num + 1; nnum < MAX; nnum++) {
if (arr[nnum] == 0 || m[nnum] & bits) continue;
dfs(ans, nnum, bits | m[nnum], sum * arr[nnum] % mod);
}
}
int qpow(int a, int b) {
long long ans = 1, tmp = a;
while (b) {
if (b & 1) ans = (ans * tmp) % mod;
tmp = (tmp * tmp) % mod;
b >>= 1;
}
return ans;
}
};