母牛们不但创建了它们自己的政府而且选择了建立了自己的货币系统。由于它们特殊的思考方式,它们对货币的数值感到好奇。
传统地,一个货币系统是由1,5,10,20 或 25,50, 和 100的单位面值组成的。
母牛想知道有多少种不同的方法来用货币系统中的货币来构造一个确定的数值。
举例来说, 使用一个货币系统 {1,2,5,10,…}产生 18单位面值的一些可能的方法是:18x1, 9x2, 8x2+2x1, 3x5+2+1,等等其它。 写一个程序来计算有多少种方法用给定的货币系统来构造一定数量的面值。保证总数将会适合long long (C/C++) 和 Int64 (Free Pascal),即在0 到2^63-1之间。
输入输出格式
输入格式:
货币系统中货币的种类数目是 V (1<=V<=25)。要构造的数量钱是 N (1<= N<=10,000)。
第一行: 二个整数,V 和 N 。
第二行: 可用的货币的面值 。
输出格式:
输出格式:
单独的一行包含那个可能的用这v种硬币凑足n单位货币的方案数。
输入输出样例
输入样例#1: 复制
3 10
1 2 5
输出样例#1: 复制
10
说明
翻译来自NOCOW
USACO 2.3
补基础 搞一波完全背包qwq 啥也不会啊菜死
题意:询问给定一些货币的价值 再给定一个数字 请问有多少种方法可以凑出这个价值的数 (每种硬币无限) 完全背包dp 首先我们应该设一个朴素的dp[i][j]表示 买了前i种物品现在在买第i种物品 凑到价值j的方案数首先一个朴素的转移就是我枚举他是由前一个的几倍a[i]转移过来的 如 dp[i][j]=dp[i-1][j-x*a[i]]+1时间复杂度大致是物品数*容量*sigma(容量/每件的花费)时间显然是不可以接受的那么完全背包还有个优化 不妨转换一下定义dp[i][j]表示前i种物品填满了j的容量
在完全背包中,v变化的区间是顺序循环的原因:完全背包的特点是每种物品可选无限件,在求解加选第i种物品带来的收益f[i][v]时,在状态f[i][v-c[i]]中已经尽可能多的放入物品i了,此时在f[i][v-c[i]]的基础上,我们可以再次放入一件物品i,此时也是在不超过背包容量的基础下,尽可能多的放入物品i。
即有了由于第一维在递推中可以从上一维继承所以dp[j]+=dp[j-a[i]]
#include<cstdio>
#include<algorithm>
#define N 11000
#define inf 0x3f3f3f3f
using namespace std;
inline char gc(){
static char now[1<<16],*S,*T;
if (T==S) {T=(S=now)+fread(now,1,1<<16,stdin);if (T==S) return EOF;}
return *S++;
}
inline int read(){
int x=0;char ch=gc();
while(ch<'0'||ch>'9') ch=gc();
while(ch<='9'&&ch>='0') x=x*10+ch-'0',ch=gc();
return x;
}
int v,n,a[30];long long dp[N];
int main(){
freopen("bzoj1708.in","r",stdin);
v=read();n=read();
for (int i=1;i<=v;++i) a[i]=read();dp[0]=1;
for (int i=1;i<=v;++i)
for (int j=a[i];j<=n;++j) dp[j]+=dp[j-a[i]];
printf("%lld",dp[n]);
return 0;
}