就一个基础的背包dp;
记dp[i][j]为考虑前i个金币,价值为j有多少种取法。
所以状态转移方程为
在第二位数不超过K的情况下
j = 0 dp [ i ] [ t * a [ i ] ] = 1(t ! = 0)
j ! = 0 dp [ i ] [ t * a [ i ] + j ] + =dp [ i-1] [ j ];
最后答案就是dp[ n ] [ k ];
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
const int N=5+1e3;
const int MOD=100000007;
int dp[55][N];
int a[55],c[55];
int main()
{
int T,n,i,j,k;
int ca=0;
cin>>T;
while(T--)
{
cin>>n>>k;
for(i=1;i<=n;i++)
cin>>a[i];
for(i=1;i<=n;i++)
cin>>c[i];
memset(dp,0,sizeof(dp));
for(i=1;i<=n;i++)
for(j=1;j<=c[i];j++)
if(j*a[i]<=k) dp[i][j*a[i]]=1;
for(i=1;i<=n;i++)
{
for(int j=1;j<=k;j++)
{
for(int t=0;t<=c[i];t++)
if(j+t*a[i]<=k) dp[i][j+t*a[i]]=(dp[i][j+t*a[i]]+dp[i-1][j])%MOD;
}
}
printf("Case %d: %d\n",++ca,dp[n][k]%MOD);
}
return 0;
}