小Q的歌单

小Q的歌单

题目描述:

小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取模的结果

输入示例:
5
2 3 3 3

输出示例:
9

解析:

题目看起来比较复杂,我们可以先将题目简单化理解,比如:现在小Q有X张1元与Y张5元,现在小Q想用K元去买一张CD。当然每张钱只能在总钱数里出现一次(总不能把1张钱用两次吧)。问有多少种方法能用这两张面值相同的人民币凑够K元。

假如用X张面值1元的凑出N张,能有多少种方法?这时我们可以借助到杨辉三角
这里写图片描述
假如有6张1元的,现在需要2张,则有15种不同的搭配方法(虽然都是1元,但它们都有不同的序号~)。

只用Y张5元的凑出来N张共有多少种方法也是同理。

现在要用两种不同的面值凑出来K元则要满足三种条件,所消耗面值1元的不能超过X张,面值5元的不能超过Y张,而且凑出来的总额必须是K。
如果此时用i(i<=X)张1元,则有这三个公式必须同时满足才能满足需求:
i*1 <= k && (k - i * 1)/5 <= Y && (i * 1 + Y * 5)%k == 0

当满足条件后,这时再根据1元面值,共有的X个中需要的i个,求出1元的组合种数,乘上5元的组合种数,就是两种组合一共有多少种的种数答案。

以下是代码:
#include <iostream>
using namespace std;

long long arr[101][101];
const long long model = 1000000007;
void Init()
{
    int i, j;
    arr[0][0] = 1;
    for (i = 1; i < 101; i++)
    {
        arr[i][0] = 1;
        for (j = 1; j < 101; j++)
            arr[i][j] = (arr[i - 1][j - 1] + arr[i - 1][j]);
    }
}

int main()
{
    int x, y, a, b, i, k;
    int num = 0;
    cin >> k;
    cin >> a >> x >> b >> y;
    Init();
    for (i = 0; i <= x; i++)
    {
        if (i*a <= k && (k-i*a)/b <= y && (k-a*i)%b == 0)
        {
            num = (num + (arr[x][i] * arr[y][(k - i * a) / b]) % model) % model;
        }
    }
    cout << "共有" << num << "种方法" << endl;
    system("pause");
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值