问题描述
小E想知道一个给定集合中,有多少个子集满足以下条件:
- 子集内的所有元素数量大于 1。
- 子集内的所有元素两两之间互为倍数关系。
由于结果可能非常大,输出的结果需要对 109+7109+7 取模。
测试样例
样例1:
输入:
n = 5,a = [1, 2, 3, 4, 5]
输出:6
样例2:
输入:
n = 6,a = [2, 4, 8, 16, 32, 64]
输出:57
样例3:
输入:
n = 4,a = [3, 6, 9, 12]
输出:5
题目要求我们从给定的整数集合中,找到所有满足以下条件的子集:
- 子集内的元素数量大于 1。
- 子集内的所有元素两两之间互为倍数关系。
思路分析
-
倍数关系:两个数
x和y互为倍数关系,意味着x % y == 0或y % x == 0。这意味着在一个子集中,所有元素的任意两两数都要满足这个倍数条件。 -
动态规划 + 排序:
- 首先,可以将数组进行排序,因为如果数组是升序的,那么只需要检查每个数和它之前的数的倍数关系。
- 设
dp[i]表示以a[i]为最大元素的符合条件的子集的个数。 - 对于每个
a[i],我们可以尝试找到所有a[j](j < i),满足a[i] % a[j] == 0,然后把以a[j]为最大元素的子集加入到a[i]的子集中。 - 最终的答案是所有
dp[i]中大于 1 的子集数量的和。
-
模块化计算:
- 由于结果可能非常大,需要对
10^9 + 7取模。
- 由于结果可能非常大,需要对
步骤
- 排序:对数组进行排序,保证我们从小到大检查每个数。
- 动态规划:使用
dp数组来记录每个数可以构成的子集个数。 - 更新子集:对于每个元素
a[i],检查之前的所有元素a[j](j < i),如果a[i] % a[j] == 0,那么可以把a[j]的所有子集扩展到a[i]。 - 取模:计算结果时,记得对
10^9 + 7取模
MOD = 10**9 + 7
def solution(n, a):
# 排序数组
a.sort()
# dp[i]表示以a[i]为最大元素的符合条件的子集个数
dp = [0] * n
total = 0
for i in range(n):
dp[i] = 1 # 至少可以是a[i]自己组成的子集
# 检查前面所有可能的子集
for j in range(i):
if a[i] % a[j] == 0:
dp[i] = (dp[i] + dp[j]) % MOD
# 仅计算包含多个元素的子集(即dp[i] > 1)
total = (total + dp[i]) % MOD
# 最终结果减去所有单元素子集
result = (total - n + MOD) % MOD
return result
# 测试样例
print(solution(5, [1, 2, 3, 4, 5])) # 输出:6
print(solution(6, [2, 4, 8, 16, 32, 64])) # 输出:57
print(solution(4, [3, 6, 9, 12])) # 输出:5
解释
-
初始化和排序:
- 我们首先对数组
a进行排序,以保证我们可以从小到大检查每个数的倍数关系。
- 我们首先对数组
-
动态规划:
- 对于每个数
a[i],我们假设它单独形成一个子集(即dp[i] = 1),然后尝试找出所有能与a[i]形成倍数关系的前一个数a[j](j < i且a[i] % a[j] == 0),将a[j]的子集扩展到a[i],因此dp[i] += dp[j]。
- 对于每个数
-
总和计算:
- 我们通过累加所有
dp[i]来得到所有子集的数量,但是这个计数中包含了所有单个元素子集,所以最后需要减去n(单个元素的子集数量)。
- 我们通过累加所有
-
取模:
- 因为答案可能非常大,我们在每一步计算时都对
10^9 + 7取模,保证计算不会溢出。
- 因为答案可能非常大,我们在每一步计算时都对
时间复杂度
- 排序:
O(n log n)。 - 动态规划:对于每个
a[i],我们需要遍历它之前的所有数,所以总的时间复杂度是O(n^2)。 - 因此,整体时间复杂度是
O(n^2),在n较小的情况下可以接受。
测试样例解析
-
输入:
n = 5, a = [1, 2, 3, 4, 5]-
排序后的数组:
[1, 2, 3, 4, 5] -
子集如下:
[1, 2],[1, 4],[1, 2, 4],[2, 4],[3, 6],[6]- 最终结果为
6。
-
-
输入:
n = 6, a = [2, 4, 8, 16, 32, 64]- 排序后的数组:
[2, 4, 8, 16, 32, 64] - 通过计算所有符合条件的子集,最终结果为
57。
- 排序后的数组:
-
输入:
n = 4, a = [3, 6, 9, 12]- 排序后的数组:
[3, 6, 9, 12] - 最终结果为
5。
- 排序后的数组: