歌单
问题描述:
小Q有X首长度为A的不同的歌和Y首长度为B的不同的歌,现在小Q想用这些歌组成一个总长度正好为K的歌单,每首歌最多只能在歌单中出现一次,在不考虑歌单内歌曲的先后顺序的情况下,请问有多少种组成歌单的方法。 输入描述: 每个输入包含一个测试用例。 每个测试用例的第一行包含一个整数,表示歌单的总长度K(1<=K<=1000)。 接下来的一行包含四个正整数,分别表示歌的第一种长度A(A<=10)和数量X(X<=100)以及歌的第二种长度B(B<=10)和数量Y(Y<=100)。保证A不等于B。 输出描述: 输出一个整数,表示组成歌单的方法取模。因为答案可能会很大,输出对1000000007取模的结果。 示例1 输入 5 2 3 3 3 输出 9
解答:
#include<bits/stdc++.h> using namespace std; const int mod = 1000000007; int main() { int k;//代表输入歌单长度 int numA,lenA,numB,lenB; cin>>k; cin>>numA>>lenA>>numB>>lenB; int len = numA + numB + 1; int* lenAB = new int[len];//新建一个数组,用dp来做 for(int i = 1;i <= numA;i++ ){ lenAB[i] = lenA; } for(int i = numA+1;i<len;i++){ lenAB[i] = lenB; } int **dp = new int*[k+1]; for(int i = 0;i <= k;i++){ dp[i] = new int[len]; } for(int i = 0;i<len;i++){ dp[0][i] = 1; } for(int i = 1;i<=k;i++){ dp[i][0] = 0; } for(int i = 1;i<=k;i++){ for(int j=1;j<len;j++){ if(i>=lenAB[j]){ dp[i][j] = (dp[i][j-1] + dp[i-lenAB[j]][j])%mod; }else{ dp[i][j] = dp[i][j-1]; } } } //打印 // for(int i = 0;i <= k;i++){ // for(int j = 0;j<len;j++){ // cout<<dp[i][j]<<" "; // } // cout<<endl; // } cout<<dp[k][len-1]<<endl; }