Time Limit: 1 second
Memory Limit: 32 MB
问题描述
母牛们不但创建了他们自己的政府而且建立了自己的货币系统。他们对货币的数值感到好奇。传统地,一个货币系统是由1,5,10,20或25,50,100的单位面值组成的。母牛们想知道用货币系统中的货币来构造一个确定的面值,有多少种不同的方法。
举例来说,使用一个货币系统{1,2,5,10……}产生18单位面值的一些可能的方法是:18×1,9×2,8×2+2×1,3×5+2+1等等。
写一个程序来计算用给定的货币系统来构造一个确定的面值有多少种方法。
第一行:两个整数V(1≤V≤25)和n(1≤n≤10000)。
第二~V+1行:可用的货币V个整数(每行一个)
Output
一个数据,表示可能构造的方案数。
3 10 1 2 5Sample Output
10
【题解】
用f[j]表示面值为j的方案数,一开始除f[0]等于1外,其他所有f[j]都为0,然后用完全背包的方式更新解。f[j] = f[j] + f[j-w[i]];即如果j-w[i]可以构造出来,那么再加上一个面值为w[i]的就可以了,所以j-w[i]有多少方案,f[j]就也可以加上这么多方案。
有几个测试点要用long long 才能存得下。
【代码】
#include <cstdio> #include <cstring> int v,n,w[30]; long long f[10010]; void input_data() { scanf("%d%d",&v,&n); for (int i = 1;i <= v;i++) scanf("%d",&w[i]); } void get_ans() { memset(f,0,sizeof(f));//因为要恰好。所以其他f[j]要置为0 f[0] = 1; //f[0]即什么都不用就能构造出来 可以看做奠基 for (int i = 1;i <= v;i++) //枚举前v个物品 for (int j = w[i]; j <= n;j++) //用完全背包的方法来更新解。 f[j] = f[j] + f[j-w[i]]; } void output_ans() { printf("%I64d",f[n]); } int main() { //freopen("F:\rush.txt","r",stdin); input_data(); get_ans(); output_ans(); return 0; }