小Q的歌单(2018腾讯笔试题)

还在实习的我今天有同学问我了一道编程题说是2018年腾讯校招的笔试题(我只是个即将大四的菜逼-哈哈哈)

小Q的歌单:小Q有x首长度为A的不同歌和y首长度为B的歌,现在小Q想用这些歌组成一个总长度

正好为k的歌单,每首歌只能在歌单中出现一次,在不考虑歌单内歌曲的先后顺序的情况下问有多少种组合方式

输入描述:

每个输入包含一个测试用例

每个测试用例的第一行包含一个整数,表示歌单的总长度(当然得大于0咯)

接下来一行输入四个整数分别表示第一个歌的长度a和数量x,第二首歌的长度b和数量y,保证a!=b

输出描述:

输出一个整数,表示组成歌单的方法取模

#include<stdio.h>

long long c[105][105];

const int mod = 1000000007;//为什么要用100000007呢其实我也不是很清楚,这里可能只是需要一个很大很大的基数

void init()//建一个杨辉三角  至于为什么要建一个杨辉三角下面我会详细说明

{

    int i,j;

    c[0][0] = 1;

    for(i=1;i<101;++i)

    {

        c[i][0]=1;

        for(j=1;j<101;++j)

        {

            c[i][j]=(c[i-1][j-1]+c[i-1][j])%mod;

        }

    }

}

int main()

{

    int k,a,b,x,y;

    long long ans=0;

    int i;

    init();

    scanf(“%d”,&k);

    scanf(“%d%d%d%d”,&a,&x,&b,&y);2 3 3 3

    for(i=0;i<x+1;++i)

    {

        if(i*a<k+1 && (k-i*a)%b == 0 && (k-a*i) / b < y+1)//判断组合

        {

            ans=(ans + (c[x][i]*c[y][(k-a*i)/b]) % mod) % mod;//为什么是*呢,因为是排列

            break;//进入到if里其实就可以break了,这样避免往后的判断能降低时间复杂度,增加效率

        }

    }

    printf(“%lld\n”,ans);

    return 0;

}

下面讲一下杨辉三角的作用:

 

1

1 1

1 2 1

1 3 3 1

1 4 6 4 1

1 5 10 10 5

1 6 15 20 15        

比如输入:

5 (总长度5)

3 4 5 6                   4个长度为3的A 6个长度为5的B

6 (六种组合方式)

ans=(ans + (c[x][i]*c[y][(k-a*i)/b]) % mod) % mod;

当i=0时If条件就已经成立c[x][0]=1   (k-a*i)/b=1(几个b可以组成)

c[4][0]*c[6][1]=1*6=6

因为啥呢4个长度为3的a(杨辉三角第四行)  6个长度为5的b(杨辉三角第6行)

下面是我在linux下测试的结果:

《小Q的歌单(2018腾讯笔试题)》

 

如果还没理解自己再输入几个组合试试对比杨辉三角

方法相同自己理解吧!

 

    原文作者:杨辉三角问题
    原文地址: https://blog.csdn.net/qq_39771637/article/details/81222944
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞