2018腾讯春招技术岗面试编程题

2018腾讯春招

  • 2018腾讯春招
    • 背包问题

2018腾讯春招

背包问题

题目描述: 小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

输出例子1:
9

**分析:**这道题目难点在求组合的那里,数据会非常的大,所以可以借助杨辉三角来做。

#include 
using namespace std;
long long arr[101][101];

void init() {
    // 创建一个杨辉三角如下:
    //  1
    //  1 2 1
    //  1 3 3 1
    //  1 4 6 4 1
    //  1 5 10 10 5 1
    // 根据数学的归纳公式:c(n, k) = c(n-1, k-1) + c(n - 1, k).
    for (int i = 0; i < 101; i++)
        for (int j = 0; j < 101; j++)
            arr[i][j] = 0;
    arr[0][0] = 1;
    for (int i = 1; i < 101; i++) {
        arr[i][0] = 1;
        for (int j = 1; j < 101; j++) {
            arr[i][j] = (arr[i - 1][j - 1] + arr[i - 1][j]) % 1000000007;
        }
    }
}

int main() {
    init();
    int k, a, x, b, y;
    scanf("%d%d%d%d%d", &k, &a, &x, &b, &y);
    long long sum = 0;
    for (int i = 0; i <= x; i++) {
        for (int j = 0; j <= y; j++) {
            if (a != b) {
                if ((a * i + b * j) == k) {
                    sum += (arr[x][i] * arr[y][j]);
                } else if ((a * i + b * j) > k) {
                    break;
                }
            }
        }
    }
    cout << sum % 1000000007 << endl;

    return 0;
}

你可能感兴趣的:(春招刷题笔记)