题目链接:https://cn.vjudge.net/contest/173831#problem/M


题意:给你n种硬币,每种有固定的数量,问你在1到m中能表示几种价格。。

题解:肯定是个DP了,很容易看出来是个多重背包,然后想都没想搞了二级制优化,

发现仍然TLE(感觉自己好弱啊。。)但其实仔细想想你会发现多重背包无非是每一种

金币能多用几次,你唯一不能解决的不就是当前价格表示出来了,但是你不知道用了几个

当前所用该面值金币的数量,呢很好办啊(暴力是会超时的),开一个数组,标记组成该

价格用了多少当前所用该面值金币即可。代码简单,也比二进制优化更省时。。。

#include<map>  
#include<stack>  
#include<queue>  
#include<vector>  
#include<math.h>  
#include<stdio.h>  
#include<iostream>  
#include<string.h>  
#include<stdlib.h>  
#include<algorithm>  
using namespace std;  
typedef long long  ll;  
#define inf 1000000000  
#define mod 1000000007   
#define  maxn  100005
#define  lowbit(x) (x&-x)  
#define  eps 1e-10  
int dp[maxn],a[maxn],b[maxn],num[maxn];
/*void wanquan(int u,int w,int v)
{
	for(int j=u;j<=v;j++)
		dp[j]=max(dp[j],dp[j-u]+w);
}
void dan(int u,int w,int v)
{
	for(int j=v;j>=u;j--)
		dp[j]=max(dp[j],dp[j-u]+w);
}
void work(int u,int w,int num,int v)
{
	if(w*num>=v)
		wanquan(u,w,v);
	else
	{
		int k=1;
		while(k<num)
		{
			dan(k*u,k*w,v);
			num-=k;
			k*=2;
		}
		dan(num*u,num*w,v);
	}
}*/
int main(void)
{
	int n,m,i,ans,j;
	while(scanf("%d%d",&n,&m))
	{
		ans=0;
		if(m==0 && n==0)
			break;
		memset(dp,0,sizeof(dp));
		for(i=1;i<=n;i++)
			scanf("%d",&a[i]);
		for(i=1;i<=n;i++)
			scanf("%d",&b[i]);
		dp[0]=1;
		for(i=1;i<=n;i++)
		{
            for(j=0;j<=m;j++)
				num[j]=0;
			for(j=a[i];j<=m;j++)
			{
				if(!dp[j] && dp[j-a[i]] && num[j-a[i]]<b[i])
				{
					num[j]=num[j-a[i]]+1;
					dp[j]=1;
					ans++;
				}
			}
		}
		printf("%d\n",ans);
	}
	return 0;
}