组合数学--彭彭礼品店

题意

问题描述:

  彭彭是个既漂亮又心肠好的女孩,她经营了一家礼品店,新年快来了,她想给她认识的所有小朋友们(很多很多)送些精美的小礼物,她的店中现在有K种一样大小的礼物,当然每种礼品的数量足够多,她还有一些礼品盒子,每个盒子均能盛放N个礼物。

  彭彭想给每个小朋友不同的惊喜,因此她不允许任何两个盒子的礼品组合是相同的,但考虑到一些小朋友(如敏敏,佳芳等人)的特殊喜好,有些礼品必须在礼品盒中出现且要达到一定的数量,而另外一些淘气的小朋友,如明明,铁伟,总是喜欢礼品盒装的慢慢的,可是彭彭不想为这些有着特殊需求的小朋友单独准备礼品盒,因为礼品盒一旦被封装,她就无法分清楚那个盒子究竟应该送给谁。可是彭彭很聪明,经过一个晚上的努力思考,她终于想到了一个好办法,那就是让每个礼品盒都满足这些特殊的需求,这样她就可以把任意的盒子送给任意的小朋友了。彭彭在为自己聪明的脑袋感到骄傲的同时,又想知道她最多可以给多少个小朋友送礼物,这可难坏了她,那么现在就请你试试吧!

输入:

  对每组输入第一行先给出K(1≤K≤50)表示礼品的种类,N(1≤N≤40)表示礼品盒的最大容量;接着第二行给K个数a[k],分别表示对于第K个物品至少应放a[k]个(0≤a[k])。

输入以“0 0”结束。

输出:

  最多可送出的礼物盒数量,占一行。

样例输入

  4 20

  3 1 0 5

  0 0

样例输出

  364

分析

问题可以这么转化,我们开始可以处理对于每种礼品的最少数量ai,每输入一个ai,n-=ai;
那么最后问题等于问你,x1+x2+.....+xk=n,这个多元一次不定方程的非负解种类数,因为n把所以ai都减了,肯定使得每种非负解
都会满足每种礼品的最少数量,那么怎么算呢?
先看一下这个y1+y2+....+yk=n, 多元一次不定方程的正整数解的种类数,对于n可以分成n份都是1的,需要切n-1个位置,那么正整数解的种类数就是
从n-1个位置选出k-1个位置,假设我们令ai=xi+1,那么x1+x2+.....+xk=n多元一次不定方程的非负解种类数等价于
a1+a2+.....+ak=n+r的正整数解种类数,也就是从n+k-1个位置选出k-1个位置,具体看代码

代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll c(int n,int m){
    if(m<n-m) m=n-m;
    ll ans=1;
    for(int i=n;i>=m+1;i--)
      ans*=i;
      for(int j=1;j<=n-m;j++)ans/=j;
      return ans;
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    ll n,i,k,a,h;
    while(cin>>n>>k){
        
        for(i=0;i<k;i++)
        {
            cin>>a;
            n-=a;
        }
        cout<<c(n+k-1,k-1)<<endl;
    }
    return 0; 
}

转载于:https://www.cnblogs.com/mch5201314/p/9792774.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值