问题描述
小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则会超时,数据必需放在全局变量中,放在局部变量中会数据溢出