组合数学--彭彭礼品店

题意

问题描述:

  彭彭是个既漂亮又心肠好的女孩,她经营了一家礼品店,新年快来了,她想给她认识的所有小朋友们(很多很多)送些精美的小礼物,她的店中现在有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; 
}
posted @ 2018-10-15 18:50  ChunhaoMo  阅读(121)  评论(0编辑  收藏  举报