题解:小R的雪球滚落计算

116 阅读3分钟

问题分析

题意:

在一座高度为 H 的山上,每个高度 i 处生成了 a_i 个雪球。当雪球从海拔高度 i 滚到地面时,它的体积会膨胀 x^i 倍。也就是说,雪球的初始体积为 1,滚动距离 i 会使体积变成 1 * x^i。我们需要计算所有滚落到地面的雪球的总体积,并对结果取模 10^9 + 7

你的任务是帮助计算所有雪球滚落到地面的总体积。

问题理解

  1. 输入:

    • H: 山的高度。
    • x: 雪球体积膨胀的倍数。
    • a: 一个长度为 H 的列表,表示每个高度 i 处的雪球数量。
  2. 输出:

    • 所有雪球滚落到地面的总体积,对 10^9 + 7 取模。

数据结构与算法选择

  1. 数据结构:

    • 使用一个列表 a 来存储每个高度的雪球数量。
  2. 算法步骤:

    • 对于每个高度 i,计算雪球滚落到地面的体积膨胀倍数 x^i
    • 计算每个高度的雪球总体积,并累加到总和。
    • 对总和取模 10^9 + 7

公式:

  • 对于每个高度 ii,雪球膨胀后的体积为 ai⋅xia_i \cdot x^i。
  • 总体积为 sum=∑i=0H−1ai⋅xi\text{sum} = \sum_{i=0}^{H-1} a_i \cdot x^i。

算法设计

  1. 快速幂

    • 由于直接计算 xix^i 会随着 ii 增大而变得很慢,因此使用快速幂法计算 )x^i mod (10^9 + 7),将复杂度从 O(i) 降到 O(log⁡i)。
  2. 遍历计算总体积

    • 遍历每个高度 ii,对每一高度的雪球数量 a_i 和膨胀体积 x^i 求积。
    • 将所有结果累加,并对 10^9 + 7 取模。
  3. 取模技巧

    • 每次计算x^i mod (10^9 + 7) 和 (a_i \cdot x^i) mod (10^9 + 7) 时都取模,防止数值溢出。

实现代码

def solution(H, x, a):
    MOD = 10**9 + 7

    # 快速幂计算 x^i % MOD
    def fast_power(base, exp, mod):
        result = 1
        while exp > 0:
            if exp % 2 == 1:
                result = (result * base) % mod
            base = (base * base) % mod
            exp //= 2
        return result

    total_volume = 0
    for i in range(H):
        # 计算 x^i % MOD
        power_x_i = fast_power(x, i, MOD)
        # 计算当前高度贡献的体积,并累加到总和
        total_volume = (total_volume + a[i] * power_x_i) % MOD

    return total_volume

# 测试样例
print(solution(4, 5, [1, 3, 2, 4]))  # 输出: 2830
print(solution(2, 5, [1, 2]))        # 输出: 55
print(solution(3, 3, [2, 1, 1]))     # 输出: 42

样例解释

样例 1:

输入:H = 4, x = 5, a = [1, 3, 2, 4]

  • 高度 0:1⋅50=11 \cdot 5^0 = 1
  • 高度 1:3⋅51=153 \cdot 5^1 = 15
  • 高度 2:2⋅52=502 \cdot 5^2 = 50
  • 高度 3:4⋅53=5004 \cdot 5^3 = 500
  • 总体积:1+15+50+500=28301 + 15 + 50 + 500 = 2830。

样例 2:

输入:H = 2, x = 5, a = [1, 2]

  • 高度 0:1⋅50=11 \cdot 5^0 = 1
  • 高度 1:2⋅51=102 \cdot 5^1 = 10
  • 总体积:1+10=551 + 10 = 55。

复杂度分析

  1. 时间复杂度

    • 快速幂计算 x^i 的复杂度为 O(log⁡i),对每个高度进行累加的复杂度为 O(Hlog⁡H)
  2. 空间复杂度

    • 快速幂只需要常数空间,整体空间复杂度为O(1)。