题目描述:小Q有X首长度为A的不同的歌和Y首长度为B的不同的歌,现在小Q想用这些歌组成一个总长度正好为K的歌单,每首歌 最多只能在歌单中出现一次,在不考虑歌单内歌曲的先后顺序的情况下,请问有多少种组成歌单的方法。
先试探一下看个图: 右下角即为所求
用vector< vector<int> > st的数据结构 st[i][j] 表示前j个歌长能组合成i歌长的情况
用vector<int> st 来保存单首歌长3 3 3 2 2 2
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int main()
{
int k, lenx, x, leny, y;
while (cin >> k >> lenx >> x >> leny >> y)
{
const int mod = 1e9+7;
vector<int> v;
for (int i = 0; i < x; ++i)
v.push_back(lenx);
for (int j = 0; j < y; ++j)
v.push_back(leny);
vector<vector<int> > st(k + 1, vector<int>(x + y, 1));
for (int i = 1; i < k + 1; ++i) //st[i][j] i代表
{
if (v[0]!=i)
st[i][0] = 0; //考虑下标为1的那一列
for (int j = 1; j < x + y; ++j)
{
if (i >= v[j]) // 合并后歌单长度大于单首歌长
{
st[i][j] = (st[i - v[j]][j - 1] + st[i][j - 1]) % mod;
}
else
st[i][j] = (st[i][j - 1])% mod;
}
}
cout << st[k].back()<< endl;
}
system("pause");
return 0;
}
最重要的是规律: st[i][j] = (st[i - v[j]][j - 1] + st[i][j - 1]) % mod; 为了满足第2行规律需要把第0行先填充为全1
为了满足第1列规律需要把 行数i!=v[0]的置为1 这样就能保证整个st[i][j]都能满足规律
结果: