ai助学算法

194 阅读5分钟

中等:及格的组合方式 题目:### 问题描述

小S在学校选择了3门必修课和n门选修课程来响应全面发展的教育政策。现在期末考核即将到来,小S想知道他所有课程的成绩有多少种组合方式能使他及格。及格的条件是所有课程的平均分不低于60分。每门课程的成绩是由20道选择题决定,每题5分,答对得分,答错不得分。为了计算方便,你需要将结果对202220222022取模。

ai帮助理解题意概括大意如下

小S选了3门必修课和 nnn 门选修课,每门课通过20道选择题(每题5分)评分,满分为100分。为了及格,所有课程的平均分必须不低于60分。

题目要求计算所有可能的成绩组合,使得平均分不低于60分,并对结果取模 202220222022202220222022202220222022。

输入输出

  • 输入:一个整数 nnn,表示选修课的数量。
  • 输出:符合条件的成绩组合数,对 202220222022202220222022202220222022 取模

随后ai给出解题思路: 通过动态规划解决,动态规划的主要设计思路:使用二维动态规划数组dp[i][j]其中dp[i][j]表示前前i门课可以获得总分为j的组合数。 转移方程:对于每门客的成绩从0-20进行遍历,根据前一个来更新。 经过思考得出答案

import java.math.BigInteger;

public class Main {
    public static String solution(int n) {
        // 模数
        final long MOD = 202220222022L;
        // dp数组
        long[][] dp = new long[n + 4][20 * (n + 3) + 1];

        // 初始化dp
        dp[0][0] = 1;

        // 动态规划填表
        for (int i = 1; i <= n + 3; i++) {
            for (int j = 0; j <= 20 * (n + 3); j++) {
                for (int k = 0; k <= 20; k++) {
                    if (j >= k) {
                        dp[i][j] = (dp[i][j] + dp[i - 1][j - k]) % MOD;
                    }
                }
            }
        }

        // 计算满足条件的组合数
        long count = 0;
        for (int j = 12 * (n + 3); j <= 20 * (n + 3); j++) {
            count = (count + dp[n + 3][j]) % MOD;
        }

        return Long.toString(count);
    }

    public static void main(String[] args) {
        // 测试用例
        System.out.println(solution(3).equals("19195617"));
        System.out.println(solution(6).equals("135464411082"));
        System.out.println(solution(49).equals("174899025576"));
        System.out.println(solution(201).equals("34269227409"));
        System.out.println(solution(888).equals("194187156114"));
    }
}

最后就是ai总结做题思路以及方法

这道题是一个典型的动态规划问题,涉及到选修课程的组合数计算。目标是求出所有课程的成绩组合数,使得平均分不低于60分,并对结果取模 202220222022202220222022202220222022。具体思路如下:

  1. 课程分数的范围

    • 每门课程有20道题,每题5分,所以每门课的成绩可能为 0 到 100 分之间的整数,且分数为 5 的倍数。
    • 小S总共有 3+n3 + n3+n 门课程,因此总成绩的范围为 000 到 20×(3+n)20 \times (3 + n)20×(3+n)。
  2. 及格条件

    • 平均分不低于60分,意味着所有课程的总分要达到 60×(3+n)=12×(3+n)60 \times (3 + n) = 12 \times (3 + n) 60×(3+n)=12×(3+n) 分。因此,只需要统计总成绩大于或等于 12×(3+n)12 \times (3 + n)12×(3+n) 的组合数。
  3. 动态规划设计

    • 使用二维动态规划数组 dp[i][j],其中 dp[i][j] 表示使用前 i 门课可以得到总分为 j 的组合数。
    • 转移方程:对于每门课的成绩从 020 进行遍历,将 dp[i][j] 更新为 dp[i-1][j-k] 的累加和,这样就可以在加入第 i 门课的基础上更新总分 j 的组合数。
  4. 初始化

    • 初始化 dp[0][0] = 1,即在选择0门课程且总成绩为0的情况下有1种组合。
  5. 组合数的求和

    • 通过遍历 dp[n+3][j](即所有 3 + n 门课程的组合)找到满足 j >= 12 \times (3 + n) 的所有组合数,求和得到符合条件的组合数。
  6. 模运算

    • 因为组合数可能非常大,所以每次累加时对 202220222022202220222022202220222022 取模,避免整数溢出。

代码分析

  • MOD 值定义:使用 MOD = 202220222022 来处理大数取模问题。

  • dp 数组初始化dp 的大小是 n + 4 行,20 * (n + 3) + 1 列。n+4 是为了包含3门必修课和 n 门选修课的总课程数。

  • 三重循环填表

    • 外层循环遍历课程数 i
    • 中间循环遍历总分 j
    • 内层循环遍历当前课程的可能分数 k(从 0 到 20)。
  • 结果计算:遍历 dp[n + 3][j],统计满足条件的组合数。

优化技巧

  1. 模数限制:每次累加时都取模 MOD,以防止整数溢出。
  2. 动态规划:利用前一行的结果来计算当前行的值,大大减少了重复计算的情况。
  3. 剪枝:内层循环中如果 j < k,直接跳过计算,减少不必要的更新操作。

复杂度分析

  • 时间复杂度:三重循环的时间复杂度约为 O((n+3)×(20×(n+3))×20)O((n + 3) \times (20 \times (n + 3)) \times 20)O((n+3)×(20×(n+3))×20),整体复杂度较高。
  • 空间复杂度:使用了一个二维数组 dp,大小为 O((n+3)×20×(n+3))O((n + 3) \times 20 \times (n + 3))O((n+3)×20×(n+3))。