Skip to content

Commit 61b49ed

Browse files
committed
feat: add solutions to lc problem: No.2572
No.2572.Count the Number of Square-Free Subsets
1 parent a02b9f6 commit 61b49ed

File tree

7 files changed

+412
-8
lines changed

7 files changed

+412
-8
lines changed

solution/1900-1999/1994.The Number of Good Subsets/README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,10 @@
7979

8080
时间复杂度 $O(n + C \times M)$,空间复杂度 $O(M)$。其中 $n$ 为 $nums$ 的长度;而 $C$ 和 $M$ 分别为题目中 $nums[i]$ 的范围和状态的个数,本题中 $C=30$, $M=2^{10}$。
8181

82+
相似题目:
83+
84+
- [2572. 无平方子集计数](/solution/2500-2599/2572.Count%20the%20Number%20of%20Square-Free%20Subsets/README.md)
85+
8286
<!-- tabs:start -->
8387

8488
### **Python3**

solution/2500-2599/2572.Count the Number of Square-Free Subsets/README.md

Lines changed: 148 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,34 +51,178 @@
5151

5252
<!-- 这里可写通用的实现逻辑 -->
5353

54+
**方法一:状态压缩动态规划**
55+
56+
注意到题目中 $nums[i]$ 的范围为 $[1, 30]$,因此我们可以预处理出所有小于等于 $30$ 的质数,即 $[2, 3, 5, 7, 11, 13, 17, 19, 23, 29]$。
57+
58+
无平方子集中,所有元素的乘积可以表示为一个或多个互不相同的质数的乘积,也即是说,每个质因数最多只能出现一次。因此,我们可以使用一个二进制数来表示一个子集中的质因数,其中二进制数的第 $i$ 位表示质数 $primes[i]$ 是否出现在子集中。
59+
60+
我们可以使用状态压缩动态规划的方法来求解本题。设 $f[i]$ 表示二进制数 $i$ 表示的子集中的质因数的乘积为一个或多个互不相同的质数的乘积的方案数。初始时 $f[0]=1$。
61+
62+
我们在 $[2,..30]$ 的范围内枚举一个数 $x$,如果 $x$ 不在 $nums$ 中,或者 $x$ 为 $4, 9, 25$ 的倍数,那么我们可以直接跳过。否则,我们可以将 $x$ 的质因数用一个二进制数 $mask$ 表示,然后我们从大到小枚举当前的状态 $state$,如果 $state$ 与 $mask$ 按位与的结果为 $mask$,那么我们可以从状态 $f[state \oplus mask]$ 转移到状态 $f[state]$,转移方程为 $f[state] = f[state] + cnt[x] \times f[state \oplus mask]$,其中 $cnt[x]$ 表示 $x$ 在 $nums$ 中出现的次数。
63+
64+
注意,我们没有从数字 $1$ 开始枚举,因为我们可以选择任意个数字 $1$,加入到无平方子集中。也可以只选择任意个数字 $1$,不加入到无平方子集中,这两种情况都是合法的。那么答案就是 $(\sum_{i=0}^{2^{10}-1} f[i]) - 1$。
65+
66+
时间复杂度 $O(n + C \times M)$,空间复杂度 $O(M)$。其中 $n$ 为 $nums$ 的长度;而 $C$ 和 $M$ 分别为题目中 $nums[i]$ 的范围和状态的个数,本题中 $C=30$, $M=2^{10}$。
67+
68+
相似题目:
69+
70+
- [1994. 好子集的数目](/solution/1900-1999/1994.The%20Number%20of%20Good%20Subsets/README.md)
71+
5472
<!-- tabs:start -->
5573

5674
### **Python3**
5775

5876
<!-- 这里可写当前语言的特殊实现逻辑 -->
5977

6078
```python
61-
79+
class Solution:
80+
def squareFreeSubsets(self, nums: List[int]) -> int:
81+
primes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]
82+
cnt = Counter(nums)
83+
mod = 10**9 + 7
84+
n = len(primes)
85+
f = [0] * (1 << n)
86+
f[0] = pow(2, cnt[1])
87+
for x in range(2, 31):
88+
if cnt[x] == 0 or x % 4 == 0 or x % 9 == 0 or x % 25 == 0:
89+
continue
90+
mask = 0
91+
for i, p in enumerate(primes):
92+
if x % p == 0:
93+
mask |= 1 << i
94+
for state in range((1 << n) - 1, 0, -1):
95+
if state & mask == mask:
96+
f[state] = (f[state] + cnt[x] * f[state ^ mask]) % mod
97+
return sum(v for v in f) % mod - 1
6298
```
6399

64100
### **Java**
65101

66102
<!-- 这里可写当前语言的特殊实现逻辑 -->
67103

68104
```java
69-
105+
class Solution {
106+
public int squareFreeSubsets(int[] nums) {
107+
int[] primes = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29};
108+
int[] cnt = new int[31];
109+
for (int x : nums) {
110+
++cnt[x];
111+
}
112+
final int mod = (int) 1e9 + 7;
113+
int n = primes.length;
114+
long[] f = new long[1 << n];
115+
f[0] = 1;
116+
for (int i = 0; i < cnt[1]; ++i) {
117+
f[0] = (f[0] * 2) % mod;
118+
}
119+
for (int x = 2; x < 31; ++x) {
120+
if (cnt[x] == 0 || x % 4 == 0 || x % 9 == 0 || x % 25 == 0) {
121+
continue;
122+
}
123+
int mask = 0;
124+
for (int i = 0; i < n; ++i) {
125+
if (x % primes[i] == 0) {
126+
mask |= 1 << i;
127+
}
128+
}
129+
for (int state = (1 << n) - 1; state > 0; --state) {
130+
if ((state & mask) == mask) {
131+
f[state] = (f[state] + cnt[x] * f[state ^ mask]) % mod;
132+
}
133+
}
134+
}
135+
long ans = 0;
136+
for (int i = 0; i < 1 << n; ++i) {
137+
ans = (ans + f[i]) % mod;
138+
}
139+
ans -= 1;
140+
return (int) ans;
141+
}
142+
}
70143
```
71144

72145
### **C++**
73146

74147
```cpp
75-
148+
class Solution {
149+
public:
150+
int squareFreeSubsets(vector<int>& nums) {
151+
int primes[10] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29};
152+
int cnt[31]{};
153+
for (int& x : nums) {
154+
++cnt[x];
155+
}
156+
int n = 10;
157+
const int mod = 1e9 + 7;
158+
vector<long long> f(1 << n);
159+
f[0] = 1;
160+
for (int i = 0; i < cnt[1]; ++i) {
161+
f[0] = f[0] * 2 % mod;
162+
}
163+
for (int x = 2; x < 31; ++x) {
164+
if (cnt[x] == 0 || x % 4 == 0 || x % 9 == 0 || x % 25 == 0) {
165+
continue;
166+
}
167+
int mask = 0;
168+
for (int i = 0; i < n; ++i) {
169+
if (x % primes[i] == 0) {
170+
mask |= 1 << i;
171+
}
172+
}
173+
for (int state = (1 << n) - 1; state; --state) {
174+
if ((state & mask) == mask) {
175+
f[state] = (f[state] + 1LL * cnt[x] * f[state ^ mask]) % mod;
176+
}
177+
}
178+
}
179+
long long ans = -1;
180+
for (int i = 0; i < 1 << n; ++i) {
181+
ans = (ans + f[i]) % mod;
182+
}
183+
return ans;
184+
}
185+
};
76186
```
77187
78188
### **Go**
79189
80190
```go
81-
191+
func squareFreeSubsets(nums []int) (ans int) {
192+
primes := []int{2, 3, 5, 7, 11, 13, 17, 19, 23, 29}
193+
cnt := [31]int{}
194+
for _, x := range nums {
195+
cnt[x]++
196+
}
197+
const mod int = 1e9 + 7
198+
n := 10
199+
f := make([]int, 1<<n)
200+
f[0] = 1
201+
for i := 0; i < cnt[1]; i++ {
202+
f[0] = f[0] * 2 % mod
203+
}
204+
for x := 2; x < 31; x++ {
205+
if cnt[x] == 0 || x%4 == 0 || x%9 == 0 || x%25 == 0 {
206+
continue
207+
}
208+
mask := 0
209+
for i, p := range primes {
210+
if x%p == 0 {
211+
mask |= 1 << i
212+
}
213+
}
214+
for state := 1<<n - 1; state > 0; state-- {
215+
if state&mask == mask {
216+
f[state] = (f[state] + f[state^mask]*cnt[x]) % mod
217+
}
218+
}
219+
}
220+
ans = -1
221+
for _, v := range f {
222+
ans = (ans + v) % mod
223+
}
224+
return
225+
}
82226
```
83227

84228
### **...**

solution/2500-2599/2572.Count the Number of Square-Free Subsets/README_EN.md

Lines changed: 130 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,25 +51,151 @@ It can be proven that there is no more than 1 square-free subset in the given ar
5151
### **Python3**
5252

5353
```python
54-
54+
class Solution:
55+
def squareFreeSubsets(self, nums: List[int]) -> int:
56+
primes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]
57+
cnt = Counter(nums)
58+
mod = 10**9 + 7
59+
n = len(primes)
60+
f = [0] * (1 << n)
61+
f[0] = pow(2, cnt[1])
62+
for x in range(2, 31):
63+
if cnt[x] == 0 or x % 4 == 0 or x % 9 == 0 or x % 25 == 0:
64+
continue
65+
mask = 0
66+
for i, p in enumerate(primes):
67+
if x % p == 0:
68+
mask |= 1 << i
69+
for state in range((1 << n) - 1, 0, -1):
70+
if state & mask == mask:
71+
f[state] = (f[state] + cnt[x] * f[state ^ mask]) % mod
72+
return sum(v for v in f) % mod - 1
5573
```
5674

5775
### **Java**
5876

5977
```java
60-
78+
class Solution {
79+
public int squareFreeSubsets(int[] nums) {
80+
int[] primes = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29};
81+
int[] cnt = new int[31];
82+
for (int x : nums) {
83+
++cnt[x];
84+
}
85+
final int mod = (int) 1e9 + 7;
86+
int n = primes.length;
87+
long[] f = new long[1 << n];
88+
f[0] = 1;
89+
for (int i = 0; i < cnt[1]; ++i) {
90+
f[0] = (f[0] * 2) % mod;
91+
}
92+
for (int x = 2; x < 31; ++x) {
93+
if (cnt[x] == 0 || x % 4 == 0 || x % 9 == 0 || x % 25 == 0) {
94+
continue;
95+
}
96+
int mask = 0;
97+
for (int i = 0; i < n; ++i) {
98+
if (x % primes[i] == 0) {
99+
mask |= 1 << i;
100+
}
101+
}
102+
for (int state = (1 << n) - 1; state > 0; --state) {
103+
if ((state & mask) == mask) {
104+
f[state] = (f[state] + cnt[x] * f[state ^ mask]) % mod;
105+
}
106+
}
107+
}
108+
long ans = 0;
109+
for (int i = 0; i < 1 << n; ++i) {
110+
ans = (ans + f[i]) % mod;
111+
}
112+
ans -= 1;
113+
return (int) ans;
114+
}
115+
}
61116
```
62117

63118
### **C++**
64119

65120
```cpp
66-
121+
class Solution {
122+
public:
123+
int squareFreeSubsets(vector<int>& nums) {
124+
int primes[10] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29};
125+
int cnt[31]{};
126+
for (int& x : nums) {
127+
++cnt[x];
128+
}
129+
int n = 10;
130+
const int mod = 1e9 + 7;
131+
vector<long long> f(1 << n);
132+
f[0] = 1;
133+
for (int i = 0; i < cnt[1]; ++i) {
134+
f[0] = f[0] * 2 % mod;
135+
}
136+
for (int x = 2; x < 31; ++x) {
137+
if (cnt[x] == 0 || x % 4 == 0 || x % 9 == 0 || x % 25 == 0) {
138+
continue;
139+
}
140+
int mask = 0;
141+
for (int i = 0; i < n; ++i) {
142+
if (x % primes[i] == 0) {
143+
mask |= 1 << i;
144+
}
145+
}
146+
for (int state = (1 << n) - 1; state; --state) {
147+
if ((state & mask) == mask) {
148+
f[state] = (f[state] + 1LL * cnt[x] * f[state ^ mask]) % mod;
149+
}
150+
}
151+
}
152+
long long ans = -1;
153+
for (int i = 0; i < 1 << n; ++i) {
154+
ans = (ans + f[i]) % mod;
155+
}
156+
return ans;
157+
}
158+
};
67159
```
68160
69161
### **Go**
70162
71163
```go
72-
164+
func squareFreeSubsets(nums []int) (ans int) {
165+
primes := []int{2, 3, 5, 7, 11, 13, 17, 19, 23, 29}
166+
cnt := [31]int{}
167+
for _, x := range nums {
168+
cnt[x]++
169+
}
170+
const mod int = 1e9 + 7
171+
n := 10
172+
f := make([]int, 1<<n)
173+
f[0] = 1
174+
for i := 0; i < cnt[1]; i++ {
175+
f[0] = f[0] * 2 % mod
176+
}
177+
for x := 2; x < 31; x++ {
178+
if cnt[x] == 0 || x%4 == 0 || x%9 == 0 || x%25 == 0 {
179+
continue
180+
}
181+
mask := 0
182+
for i, p := range primes {
183+
if x%p == 0 {
184+
mask |= 1 << i
185+
}
186+
}
187+
for state := 1<<n - 1; state > 0; state-- {
188+
if state&mask == mask {
189+
f[state] = (f[state] + f[state^mask]*cnt[x]) % mod
190+
}
191+
}
192+
}
193+
ans = -1
194+
for _, v := range f {
195+
ans = (ans + v) % mod
196+
}
197+
return
198+
}
73199
```
74200

75201
### **...**
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
class Solution {
2+
public:
3+
int squareFreeSubsets(vector<int>& nums) {
4+
int primes[10] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29};
5+
int cnt[31]{};
6+
for (int& x : nums) {
7+
++cnt[x];
8+
}
9+
int n = 10;
10+
const int mod = 1e9 + 7;
11+
vector<long long> f(1 << n);
12+
f[0] = 1;
13+
for (int i = 0; i < cnt[1]; ++i) {
14+
f[0] = f[0] * 2 % mod;
15+
}
16+
for (int x = 2; x < 31; ++x) {
17+
if (cnt[x] == 0 || x % 4 == 0 || x % 9 == 0 || x % 25 == 0) {
18+
continue;
19+
}
20+
int mask = 0;
21+
for (int i = 0; i < n; ++i) {
22+
if (x % primes[i] == 0) {
23+
mask |= 1 << i;
24+
}
25+
}
26+
for (int state = (1 << n) - 1; state; --state) {
27+
if ((state & mask) == mask) {
28+
f[state] = (f[state] + 1LL * cnt[x] * f[state ^ mask]) % mod;
29+
}
30+
}
31+
}
32+
long long ans = -1;
33+
for (int i = 0; i < 1 << n; ++i) {
34+
ans = (ans + f[i]) % mod;
35+
}
36+
return ans;
37+
}
38+
};

0 commit comments

Comments
 (0)