今天我尝试连续子串和的整除问题:小M是一个五年级的小学生,今天他学习了整除的知识,想通过一些练习来巩固自己的理解。他写下了一个长度为 n 的正整数序列 a_0, a_1, ..., a_{n-1},然后想知道有多少个连续子序列的和能够被一个给定的正整数 b 整除。 首先要解决这个问题,我们需要找出所有连续子序列的和,并计算其中可以被给定的正整数 ( b ) 整除的子序列的数量。为了提高效率,我们可以利用前缀和的概念和哈希表来快速计算子序列的和。
思路
- 前缀和:通过维护一个前缀和数组,可以快速计算任意子序列的和。
- 取模:对于任意两个前缀和,如果它们的差值可以被 ( b ) 整除,则这两个前缀和对应的子序列和也可以被 ( b ) 整除。
- 哈希表:使用哈希表记录前缀和的模 ( b ) 的出现次数。这样在遍历过程中可以快速查询已有的前缀和的模值。
以下是代码实现:
def solution(n, b, sequence):
# 前缀和
prefix_sum = 0
count = 0
# 记录前缀和模 b 的次数
mod_count = {0: 1} # mod 0 出现 1 次(代表前缀和为0的情况)
for num in sequence:
prefix_sum += num
mod_value = prefix_sum % b
# 由于 Python 的 % 可能返回负值,我们需要调整它为非负
if mod_value < 0:
mod_value += b
# 如果这个模值已经在 map 中,说明有多少个前缀和的差为 b 的倍数
if mod_value in mod_count:
count += mod_count[mod_value]
# 更新 map 中这个模值的出现次数
if mod_value in mod_count:
mod_count[mod_value] += 1
else:
mod_count[mod_value] = 1
return count
if __name__ == "__main__":
# 测试用例
print(solution(3, 3, [1, 2, 3]) == 3)
print(solution(4, 5, [5, 10, 15, 20]) == 10)
print(solution(5, 2, [1, 2, 3, 4, 5]) == 6)
代码解释
- 前缀和:在每次迭代中,累加当前数字到
prefix_sum
中。 - 模值:计算当前前缀和对 ( b ) 的模值。
- 哈希表:检查当前模值是否已经存在于哈希表中。如果存在,说明之前有相同模值的前缀和,这意味着存在子序列和可以被 ( b ) 整除。
- 更新次数:在每次更新模值出现次数后,也更新到哈希表中。
这个算法的时间复杂度为 ( O(n) ),能够高效地解决问题。
今天的实验给了我很多收获和思考的空间。在实际操作过程中,我深刻感受到设计不仅仅是一个技术性的任务,更是一门将实际业务需求转化为系统逻辑的艺术。每一个设计决策都需要在复杂的业务背景下平衡效率、完整性和未来扩展的可能性。