歌单

问题描述:

小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;
}

原文地址:https://www.cnblogs.com/lyf-sunicey/p/9335966.html