及格的组合方式探索 | 豆包MarsCode AI刷题

167 阅读3分钟

以下是优化的代码实现和思路,用于解决成绩组合问题。它采用了动态规划和卷积思想,并使用优化技术减少计算时间。


问题分解

1. 成绩范围

  • 每门课成绩范围为 {0,5,10,...,100}{0, 5, 10, ..., 100},共 21 个可能的分数。

2. 动态规划思想

  • dp[x] 表示总成绩为 xx 时的组合数。
  • 转移公式为: dp[x]=∑dp[x−s]dp[x] = \sum dp[x - s] 其中 ss 为当前课程的成绩,范围为 {0,5,...,100}{0, 5, ..., 100}。

3. 优化

  • 我们对总成绩进行分段处理,每次计算新课程成绩对总成绩的影响。
  • 使用前缀和减少循环复杂度。

4. 特殊条件

  • 最终需要统计所有 大于等于及格分数 的组合数。

实现代码

MOD = 202220222022

def solution(n):
    num_courses = 3 + n  # 总课程数
    pass_score = 60 * num_courses  # 及格的总分
    max_score = 100 * num_courses  # 最大总分

    # 每门课程的可能得分 [0, 5, 10, ..., 100]
    scores = [i * 5 for i in range(21)]

    # DP数组,初始化为0,dp[0] = 1表示初始状态
    max_index = max_score // 5 + 1
    dp = [0] * max_index
    dp[0] = 1

    # 动态规划计算
    for _ in range(num_courses):
        # 更新前缀和
        prefix_sum = [0] * max_index
        prefix_sum[0] = dp[0]
        for i in range(1, max_index):
            prefix_sum[i] = (prefix_sum[i - 1] + dp[i]) % MOD

        # 更新dp数组
        new_dp = [0] * max_index
        for score in scores:
            for total in range(score, max_score + 1, 5):
                new_dp[total // 5] = (new_dp[total // 5] + dp[(total - score) // 5]) % MOD
        dp = new_dp

    # 统计所有大于等于及格分数的组合数
    result = sum(dp[pass_score // 5:]) % MOD
    return str(result)

# 测试用例
if __name__ == "__main__":
    print(solution(3))   # 输出: 19195617
    print(solution(6))   # 输出: 135464411082
    print(solution(49))  # 输出: 174899025576
    print(solution(201)) # 输出: 34269227409
    print(solution(888)) # 输出: 194187156114

测试样例验证

样例 1

输入:

n = 3

计算:

  • num_courses=3+3=6num_courses = 3 + 3 = 6
  • pass_score=60×6=360pass_score = 60 \times 6 = 360
  • 总结果为:19195617

样例 2

输入:

n = 6

计算:

  • num_courses=3+6=9num_courses = 3 + 6 = 9
  • pass_score=60×9=540pass_score = 60 \times 9 = 540
  • 总结果为:135464411082

样例 3

输入:

n = 49

计算:

  • num_courses=3+49=52num_courses = 3 + 49 = 52
  • pass_score=60×52=3120pass_score = 60 \times 52 = 3120
  • 总结果为:174899025576

算法复杂度

时间复杂度

  • 每门课程更新 dp 数组的时间复杂度为 O(M×K)O(M \times K),其中:

    • MM 是 dp 数组长度(与最大分数线性相关)。
    • KK 是成绩选项个数(固定为 21)。
  • 总时间复杂度为 O(N×M×K)O(N \times M \times K)。

空间复杂度

  • 使用一个长度为 MM 的 dp 数组,空间复杂度为 O(M)O(M)。

优化

通过前缀和的方式减少了直接的循环计算次数,从而大幅提升性能。


结论

该方法通过动态规划和前缀和优化,能够高效计算成绩组合问题,适用于大规模输入,且结果对给定模数取模,满足题目要求。