青训营X豆包MarsCode AI刷题-2 | 豆包MarsCode AI 刷题

109 阅读2分钟

问题描述

小M是一个五年级的小学生,今天他学习了整除的知识,想通过一些练习来巩固自己的理解。他写下了一个长度为n的正整数序列 a_0, a_1, ..., a_{n-1},然后想知道有多少个连续子序列的和能够被一个给定的正整数 b 整除。

关键点

  1. 连续子序列的和

    • 需要计算所有可能的连续子序列的和。
    • 判断这些和是否能被 b 整除。
  2. 优化计算

    • 直接计算所有子序列的和会非常耗时,需要优化。
    • 使用前缀和和哈希表来优化计算过程。

解决方案

我们可以通过以下步骤来解决这个问题:

  1. 前缀和

    • 计算序列的前缀和 prefix_sum,即从序列开始到当前位置的所有元素的和。
    • 前缀和的计算公式:prefix_sum[i] = a[0] + a[1] + ... + a[i]
  2. 余数计数

    • 使用哈希表 remainder_count 来记录每个前缀和除以 b 的余数的出现次数。
    • 初始化 remainder_count 中余数为0的情况,因为前缀和为0时,余数为0。
  3. 计算子序列的和

    • 遍历序列中的每个元素,计算当前前缀和 prefix_sum
    • 计算当前前缀和除以 b 的余数 remainder
    • 如果 remainder 已经在 remainder_count 中出现过,说明存在一个子序列的和是 b 的倍数,累加计数。
    • 更新 remainder_count 中的余数计数。
  4. 返回结果

    • 返回累加的计数结果,即为满足条件的连续子序列的数量。

代码实现

def solution(n, b, sequence):
    # 初始化前缀和数组和哈希表
    prefix_sum = 0
    remainder_count = {0: 1}  # 初始化余数为0的情况,因为前缀和为0时,余数为0
    count = 0
    
    for num in sequence:
        # 计算当前前缀和
        prefix_sum += num
        # 计算当前前缀和除以b的余数
        remainder = prefix_sum % b
        
        # 如果余数已经在哈希表中出现过,说明存在一个子序列的和是b的倍数
        if remainder in remainder_count:
            count += remainder_count[remainder]
        
        # 更新哈希表中的余数计数
        if remainder in remainder_count:
            remainder_count[remainder] += 1
        else:
            remainder_count[remainder] = 1
    
    return count

# 测试样例
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

总结

通过使用前缀和和哈希表,我们可以高效地计算出有多少个连续子序列的和能够被给定的正整数 b 整除。每次计算前缀和的余数,并记录余数的出现次数,可以快速判断是否存在满足条件的子序列。最终得到的计数结果即为满足条件的连续子序列的数量。