题意:给定 n 种面值的钞票,每一种钞票有一定数量,问用这些钞票可以组成 [1,m] 中哪些价值的集合,统计可以组成的数量;
分析:组合数学,生成函数可以解,但是这题数据范围较大,所以用生成函数会T,考虑一下DP;
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int MAXN = 1e5+10;
int f[MAXN]; //f[i] 表示 能不能组成价值为 i 的钞票集合
int use[MAXN];
int A[101],C[101];
int n,m;
int main()
{
while(~scanf("%d%d",&n,&m)&&n+m)
{
for(int i=1;i<=n;i++) scanf("%d",&A[i]);
for(int i=1;i<=n;i++) scanf("%d",&C[i]);
memset(f,0,sizeof(f));
f[0]=1;
for(int i=1;i<=n;i++)
{
memset(use,0,sizeof(use)); //use数组表示在哪些价值上使用了当前种类的钞票
for(int j=0;j<=m;j++)
{
if(f[j]==0&&j>=A[i])
{
//如果价值j还没有组到过,但是价值j-A[i]组到过,且在价值j-A[i]时已经使用的当前种类钞
//票数量没有达到上限,就更新
if(f[j-A[i]]&&use[j-A[i]]<C[i]) {
f[j]=1;
use[j]=use[j-A[i]]+1;
}
}
}
}
int ans=0;
for(int i=1;i<=m;i++) if(f[i]) ans++;
printf("%d\n",ans);
}
}