LightOJ 1231 Coin Change (I) (背包计数模板题)

1231 - Coin Change (I)

PDF (English) Statistics Forum
Time Limit: 1 second(s) Memory Limit: 32 MB

In a strange shop there are n types of coins of valueA1, A2 ... An.C1, C2,... Cn denote the number of coins of valueA1, A2...
An
 respectively. You have to find the number of ways you canmakeK using the coins.

For example, suppose there are three coins 1, 2, 5 and wecan use coin 1 at most 3 times, coin 2 at most 2 times and coin 5 at most 1time. Then ifK = 5 the possible ways are:

1112

122

5

So, 5 can be made in 3 ways.

Input

Input starts with an integer T (≤ 100),denoting the number of test cases.

Each case starts with a line containing two integersn (1≤ n ≤ 50) andK (1 ≤ K ≤ 1000). The nextline contains2n integers, denotingA1, A2 ...An, C1, C2...
Cn (1 ≤ Ai≤ 100, 1 ≤ Ci ≤ 20)
. AllAiwill be distinct.

Output

For each case, print the case number and the number of waysKcan be made. Result can be large, so, print the result modulo100000007.

Sample Input

Output for Sample Input


2

3 5

1 2 5 3 2 1

4 20

1 2 3 4 8 4 2 1


Case 1: 3

Case 2: 9

题目链接:http://lightoj.com/volume_showproblem.php?problem=1231

题目大意:n种面值为a[i]的硬币,每种对应c[i]个,求能组成金额K的方案数。

解题思路:背包计数 ,dp[i][j]表示前 i 种硬币能组成面值为 j 的方案个数。每个a[i]可用0-c[i]次。递推方程为:当满足条件j-k*a[i]>=0时,dp[i][j]=dp[i-1][j]+dp[i-1][j-k*a[i]]。

代码如下:

#include <cstdio>
#include <cstring>
#define mod 100000007;
int a[52],c[52];
int dp[52][1005];
int main()
{
    int t,cnt=0,n,v,i,j,k;
    scanf("%d",&t);
    while(t--)
    {
		memset(dp,0,sizeof(dp));
        scanf("%d%d",&n,&v);
        for(i=1;i<=n;i++)
            scanf("%d",&a[i]);
        for(i=1;i<=n;i++)
            scanf("%d",&c[i]);
		dp[0][0]=1;
        for(i=1;i<=n;i++)
            for(j=0;j<=v;j++)
                for(k=0;k<=c[i];k++)
                {
                    if(j-k*a[i]>=0)
                        dp[i][j]=(dp[i][j]+dp[i-1][j-k*a[i]])%mod;
                }
		printf("Case %d: %d\n",++cnt,dp[n][v]);
    }
    return 0;
}
时间: 2024-12-28 16:37:14

LightOJ 1231 Coin Change (I) (背包计数模板题)的相关文章

Lightoj 1231 - Coin Change (I) (裸裸的多重背包)

题目链接: Lightoj  1231 - Coin Change (I) 题目描述: 就是有n种硬币,每种硬币有两个属性(价值,数目).问用给定的硬币组成K面值,有多少种方案? 解题思路: 赤果果的多重背包,简单搞一下就好了.席八!烦烦烦.今天绝对是出门刷提前没看黄历,刚开始套了一个多重背包板子,蓝而跑出来的答案并不对,改来改去就错在细节的地方. 1 #include <cmath> 2 #include <cstdio> 3 #include <cstring> 4

LightOJ 1231 - Coin Change (I) 【DP】

题目链接:http://www.lightoj.com/volume_showproblem.php?problem=1231 题意:多重部分和的解法有几种. 代码: #include <stdio.h> #include <ctime> #include <math.h> #include <limits.h> #include <complex> #include <string> #include <functional&

uva674 - Coin Change(完全背包)

题目:uva674 - Coin Change(完全背包) 题目大意:给1 5 10 25 50 这5中面值的硬币,然后给出N,问用这些钱组成N的不同方式数目.1 5 和 5 1 表示同一中,顺序不同算相同. 解题思路:完全背包. 状态方程:dp[j] += dp[ j - v[i]]: 代码: #include <cstdio> #include <cstring> const int N = 5; const int maxn = 8000; typedef long long

LightOJ 1232 - Coin Change (II) 【完全背包】

题目链接:http://www.lightoj.com/volume_showproblem.php?problem=1232 题意:每个物品价值为val[i] (>=1),每个物品有k种,组成价值为k的方案数.完全背包. 解法:完全背包计数. 代码: #include <stdio.h> #include <ctime> #include <math.h> #include <limits.h> #include <complex> #i

LightOJ 1235 - Coin Change (IV) (折半枚举)

题目链接: http://www.lightoj.com/volume_showproblem.php?problem=1235 题目描述: 给出n个硬币,每种硬币最多使用两次,问能否组成K面值? 解题思路: 因为K草鸡大,尽管n很小,但是2^n很大,无法用背包做到O(nK)的复杂度.如果暴力枚举复杂度立马飙升到O(2^(n+1)).··········· 所以引进一种新的算法,折半查找:把所要枚举的值,先把前部分的值所有情况枚举出来,再把后部分的值所有情况枚举出来并排序,结合二分进行查找. 这

Light oj 1233 - Coin Change (III) (背包优化)

题目链接:http://www.lightoj.com/volume_showproblem.php?problem=1233 题目就不说明了. 背包的二进制优化,比如10可以表示为1 2 4 3,而这些数能表示1 ~ 10的任意的数.然后类似01背包就好了. 1 #include <algorithm> 2 #include <iostream> 3 #include <cstring> 4 #include <cstdlib> 5 #include &l

Lightoj 1235 - Coin Change (IV) 【二分】

题目链接:http://www.lightoj.com/volume_showproblem.php?problem=1235 题意: 有N个硬币(N<=18).问是否能在每一个硬币使用不超过两次的情况下支付正好K的面额. 思路 : dfs构造出用这些硬币用前一半能支付的全部费用和后一半能支付的全部费用. 之后排序,枚举前一半的每一个面值在第二个里面二分寻找就可以.(或者用set保存). 代码:(set) #include <stdio.h> #include <ctime>

lightoj 1235 Coin Change (IV)(折半枚举)

话说这是俺们学校暑假集训完的一道题,刚看到以为是到水题,后来发现者复杂度也太大了,受不了了,比赛完也没搞出来,然后欣爷说这是折半枚举.然后就摸摸的学了一下,又把这道题写了一下, 所谓折半枚举就是先算出来一半,再算一半,然后用二分查找看看能不能搞到这一发状态,可以的话就是可以了, 题意:给你两个数n,k,下面再给你n个数,表示你现在有的硬币的面值,每种硬币面值的有两个,看是否可以支付k 题解思路:首先以为只有三种状态,直接dfs就好了,后来发现复杂度太大了,然后死了撸就是上面的,详细情残考代码 源

Bone Collector(01背包,模板题)

C - Bone Collector Time Limit:1000MS    Memory Limit:32768KB    64bit IO Format:%I64d & %I64u SubmitStatusPracticeHDU 2602 Description Many years ago , in Teddy's hometown there was a man who was called "Bone Collector". This man like to col