AcWing 1021. 货币系统

AcWing 1021. 货币系统

【总结】背包问题的至多/恰好/至少

一、题目描述

给你一个n种面值的货币系统,求组成面值为m的货币有多少种方案。

输入格式
第一行,包含两个整数nm

接下来n行,每行包含一个整数,表示一种货币的面值。

输出格式
共一行,包含一个整数,表示方案数。

数据范围
n15,m3000

输入样例

3 10
1
2
5

输出样例

10

二、题目解析

本题与上一题买书问题基本一模一样,只是方案数可能很大,需要用long long来存储。

状态表示
f[i][j]表示用前i种面值的货币组成面值为j的方案数
状态转移方程为f[i][j]=f[i1][j]+f[i][jv]
边界状态为f[0][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;
}

四、 扩展阅读:重复组合公式

重复组合
重复组合(Combination With Repetition)(重复组合)是组合数学中的一种计数方法,用于计算从一个包含n个对象的集合中选择k个对象的方式数,这其中 允许出现重复的对象 但是顺序不重要。

计算公式
n个不同的元素每次取出r个元素的 允许重复 组合总数为:

Cn+r1r

公式证明(插板法)

n种元素当成n个顺序摆放的盒子,r个完全相同的球,这样从n种元素中有重复取r个元素的方法就转化成,把r个同质球放入n个盒子的方法。

为什么可以这样呢?想一想,把一个球放到第i个盒子就相当于从n种元素中我们取的第i种元素,如果有多个球放在第i个盒子中,相当于从n个元素中重复了取了第i种元素。

空间中n+1条 ‘|’ 把空间分成n个盒子

举个例子n=6,也就是6个盒子

盒子1 盒子2 盒子3 盒子4 盒子5 盒子6

那么我们往里面放球用  表示
则有

我们发现,除去两边边界的 |
实际的摆放方法就是n1个 |  和 r  的不同摆放方式

所以共有n+r1个位置

我们从中选择r个位置放上小球即可

因此得到公式

Cn+r1r

利用公式估算数据范围

C3000+1513000=C301414=3014!14!×3000!=3001×...×301414!

最坏的情况

最坏的情况为存在15种货币且每种货币的价值为1,要求组合成价值3000的货币,每种货币无个数限制。

由于题目中说了,每种货币的价值并不相同,也就是上面论述的每个盒子里面不能随意放入最多r个小球,受每个盒子上限不同的限制。根据公式求出的数值,肯定是大于真实的数值。

按公式计算出的数值,要大于int的范围,如果此题数据为最坏情况,那么long long也会爆掉。

posted @   糖豆爸爸  阅读(256)  评论(0编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
历史上的今天:
2017-12-09 为预热准备更新时间列的查询办法,解决原表中没有索引的问题
2015-12-09 需要继续研究
Live2D
点击右上角即可分享
微信分享提示