4.8 KiB
一、题目描述
给你一个n
种面值的货币系统,求组成面值为m
的货币有多少种方案。
输入格式
第一行,包含两个整数n
和m
。
接下来n
行,每行包含一个整数,表示一种货币的面值。
输出格式 共一行,包含一个整数,表示方案数。
数据范围
n≤15,m≤3000
输入样例:
3 10
1
2
5
输出样例:
10
二、题目解析
本题与上一题买书问题基本一模一样,只是方案数可能很大,需要用long long
来存储。
状态表示
f[i][j]
: 用前i
种面值的货币组成面值 恰好 为j
的方案数
状态转移方程
\large f[i][j] = f[i-1][j] + f[i][j-v]
边界状态为f[i][0] = 1
三、实现代码
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 20;
const int M = 3010;
int n, m;
LL v[N];
LL f[M];
int main() {
cin >> n >> m;
f[0] = 1;
for (int i = 1; i <= n; i++) {
cin >> v[i];
for (int j = v[i]; j <= m; j++)
f[j] += f[j - v[i]];
}
printf("%lld\n", f[m]);
return 0;
}
四、 重复组合公式
计算公式
从n
个不同的元素每次取出r
个元素的 允许重复 组合总数为:
\large F(n,r)=C_{n+r-1}^r
证明
我们这样考虑:把10
个苹果分给3
人,我们就要在9
个空格里面插入2
块板,就会分为3
部分,且每部分都至少1
个,故有C_9^{2}
种。如图的插板方式,就是甲分3
个,乙分5
个,丙分2
个。
- 变式
1
将上述问题略加变化:把10
个苹果分给3
人,每人可以不分,有多少种分法?
这时我们要向第一种情况转化,可以假设甲、乙、丙三人本来都有苹果,他们都拿一个苹果出来,一起分,这样他们每人就至少要一个苹果了。
我们就要在9+3=12
个空格里面插入2
块板,就会分为3
部分,且每部分都至少1
个,故有C_{12}^2
种。如图的插板方式,就是甲分3-1=2
个,乙分8-1=7
个,丙分2-1=1
个。
- 变式
2
继续深入讨论:把10
个苹果分给3
人,甲至少要2
个,乙至少要3
个,丙可以不要,有多少种分法?
我们还要向第一种情况转化,可以假设先给甲1
个、给乙2
个、而丙自己先拿出来1
个,这样他们分余下的苹果时,每人至少要一个苹果就可以了。
我们就要在9-3+1=7
个空格里面插入2
块板,就会分为3
部分,且每部分都至少1
个,故有C_7^2
种。如图的插板方式,就是甲分3+1=4
个,乙分2+2=4
个,丙分3-1=2
个。
回到本题,理解为 变式2
, 每个盒子里可以没有被选择的数字,也就是0
个,为了适应 隔板法,通过构造的办法,我们认为每个盒子先拿出来一个,这样,最起码它最后能有1
个,也就是n+r
个小球,此时,可以放隔板的位置就是n+r-1
个,需要选择的位置数是r
:
\large F(n,r)=C_{n+r-1}^r
证毕
利用公式估算数据范围
\LARGE C_{3000+15-1}^{3000}=C_{3014}^{14}=\frac{3014!}{14!\times 3000!}=\frac{3001\times ... \times 3014}{14!}
最坏的情况
上面我们的思考和假设,都是 一样的小球,也就是对应着所以货币的面额都是1
,要求组合成价值3000
的货币,每种货币无个数限制。
由于题目中说了,每种货币的价值并不相同,也就是上面论述的每个盒子里面不能随意放入最多r
个小球,受每个盒子上限不同的限制。根据公式求出的数值,肯定是大于真实的数值。
按公式计算出的数值,要大于int
的范围,如果此题数据为最坏情况,那么long long
也会爆掉。