1231 - Coin Change (I) (简单DP)


1231 - Coin Change (I)

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 integers n (1≤ n ≤ 50) andK (1 ≤ K ≤ 1000). The nextline contains 2n 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 ways Kcan 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

 

题意: 给出n种金币的币值ai和数量ci, 和一个数k,问用这n种金币组成k,有多少种方法.

题解: dp[i][j]表示前i种金币组成j的方案种数,对于第i种金币,可以取0到c[i]个金币来组成k,于是状态的转移方程可以这样写

dp[i][j] = dp[i-1][j-x*a[i]],(1<=x<=c[i]),当x = 0时,dp[i][j] = dp[i-1][j],注意,这很重要. 当然第一维的状态可以通过滚动数组去掉;

AC代码:

/* ***********************************************
Author        :xdlove
Created Time  :2015年10月29日 星期四 20时30分14秒
File Name     :1231_Coin_Change.cpp
************************************************ */

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <memory.h>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <time.h>

using namespace std;


#define REP_ab(i,a,b) for(int i = a; i <= b; i++)
#define REP(i, n) for(int i = 0; i < n; i++)
#define REP_1(i,n) for(int i = 1; i <= n; i++)
#define DEP(i,n) for(int i = n - 1; i >= 0; i--)
#define DEP_N(i,n) for(int i = n; i >= 1; i--)
#define CPY(A,B) memcpy(A,B,sizeof(B))
#define MEM(A) memset(A,0,sizeof(A))
#define MEM_1(A) memset(A,-1,sizeof(A))
#define MEM_INF(A) memset(A,0x3f,sizeof(A))
#define MEM_INFLL(A) memset(A,0x3f3f,sizeof(A))
#define mid (((l + r) >> 1))
#define lson l, mid, u << 1
#define rson mid + 1, r, u << 1 | 1
#define ls (u << 1)
#define rs (u << 1 | 1)


typedef long long ll;
typedef unsigned long long ull;
const int INF = 0x3f3f3f3f;
const ll INFLL = 0x3f3f3f3f3f3f3f3f;
const int MAXN = 1e5 + 5;
const int MAXM = MAXN;
const int mod = 1e8 + 7;
int dp[55][1005],a[55],c[55];

int main()
{
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    int T,n,k;
    int kcase = 0;
    cin>>T;
    while(T--)
    {
        scanf("%d %d",&n,&k);
        REP_1(i,n) scanf("%d",&a[i]);
        REP_1(i,n) scanf("%d",&c[i]);
        MEM(dp);
        dp[0][0] = 1;
        for(int i = 1; i <= n; i++)
            for(int j = 0; j <= c[i]; j++)
                for(int x = k; x - j * a[i] >= 0; x--)
                {
                    if(j == 0) 
                        dp[i][x] = dp[i - 1][x];
                    else 
                        dp[i][x] += dp[i - 1][x - j * a[i]];
                    dp[i][x] %= mod;
                }
        printf("Case %d: %d\n",++kcase,dp[n][k]);
    }
    return 0;
}


你可能感兴趣的:(1231 - Coin Change (I) (简单DP))