Skip to content

Commit c3a56e6

Browse files
committed
update 1994.md
1 parent 87f67bd commit c3a56e6

File tree

2 files changed

+54
-1
lines changed

2 files changed

+54
-1
lines changed

Diff for: README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@
22
pc means programming contest, this is a repo for my summary of my contest.
33

44

5-
[1601](leetcode/state_reduction/1601.md)
5+
[1601](../)

Diff for: leetcode/state_reduction/1994.md

+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
2+
首先看到子集就本能想到状压,结合数据范围只有[1, 30],枚举可知道不可行的合数有
3+
11个,于是剩下19个数来选择,并且,由于某些数之间存在公因数大于1的情况,这些数不能组合在一起,
4+
因此,可进一步剪枝,使用状压dp可以解决。
5+
6+
此外需要注意1的特殊性:1可选可不选,并且,乘多个1不会影响当前的数的素数性质。因此,由乘法原理可得,
7+
最终答案应乘上`2 ^ cnt[1]`的贡献
8+
9+
```c++
10+
using ull = unsigned long long;
11+
ull invalid[] = {4, 8, 9, 12, 16, 18, 20, 24, 25, 27,28};
12+
ull mod = 1e9 + 7;
13+
int cnt[31], Mutex[31];
14+
template <class T>
15+
T qpow(T a, T n, T mod){
16+
T ans = 1;
17+
while(n){
18+
if(n & 1) ans = (ans * a)% mod;
19+
a = (a * a) % mod;
20+
n >>= 1;
21+
}
22+
return ans;
23+
}
24+
class Solution {
25+
int upper = 30;
26+
public:
27+
int numberOfGoodSubsets(vector<int>& a) {
28+
memset(cnt, 0, sizeof cnt);
29+
memset(Mutex, 0, sizeof Mutex);
30+
upper = 0;
31+
for(int i: a) cnt[i]++, upper = max(upper, i);
32+
for(int i: invalid) cnt[i] = 0;
33+
for(int i = 2; i <= 30; i++){
34+
for(int j = 2; j <= 30; j++){
35+
if(i != j && gcd(i, j) > 1)
36+
Mutex[i] |= 1 << j;
37+
}
38+
}
39+
auto ans = dfs(2, 0);
40+
if(cnt[1]) return (ans * qpow(2ull, 1ull*cnt[1], mod)) % mod;
41+
return ans;
42+
}
43+
ull dfs(int u, ull cur){
44+
if(u > upper) return cur > 0?1: 0;
45+
auto ans = dfs(u + 1, cur) % mod;
46+
if(cnt[u] && (Mutex[u] & cur) == 0){
47+
ans = (ans + cnt[u] * dfs(u + 1, cur | (1 << u))) % mod;
48+
}
49+
return ans % mod;
50+
}
51+
};
52+
53+
```

0 commit comments

Comments
 (0)