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

48 阅读2分钟

问题描述

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

测试样例

样例1:

输入:n = 3
输出:'19195617'

样例2:

输入:n = 6
输出:'135464411082'

样例3:

输入:n = 49
输出:'174899025576'

样例4:

输入:n = 201
输出:'34269227409'

样例5:

输入:n = 888
输出:'194187156114'

解题思路

解题方法

动态规划(dp)

状态表示

dp[i][j]表示当前的课程为第i门的时候分数为j的情况

状态转移方程

dp[i][j] = dp[i][j] + dp[i-1][j-k]

初始化

dp[0][0] = 1 表示课程为0时的得分也为0为1种情况

结果

将当前课程加上必修课程的分数大于等于总和的60%的所有情况

C++代码

#include <vector>
#include <string.h>
using namespace std;

using namespace std;
typedef long long ll;
const ll mod = 202220222022;
const int N = 1e4 + 10;
ll dp[1001][N*10];
string solution(int n) {
 // 当前课程为第i门课程时得分为j的组合数
    memset(dp,0,sizeof dp);
    dp[0][0] = 1;
    for(int i = 1; i <= n + 3; i ++){
        for(int j = 0; j <= (n + 3) * 20 * 5; j += 5){
            for(int k = 0;k <= 100; k += 5){
                if(j >= k){
                    dp[i][j] = (dp[i][j] + dp[i-1][j-k]) % mod;
                }
            }
        }
    }
    ll res = 0;
        for(int j = (n + 3) * 100; j >= (n + 3) * 60; j -= 5){
            // cout << dp[i][j] << endl;
            res = (res + dp[n+3][j]) % mod;
        }
    // res = res % mod;
    return to_string(res); 
}

总结

这是一道经典的dp问题,但是数据过大,如果用vector来开dp则会超时,数据必需放在全局变量中,放在局部变量中会数据溢出