第一次见到这个模型.   

首先,不难得出砝码的种类不会超过 $log(10^9)$ 个,然后就不会分析了qaq...  

那么,就说明一共只有 $30$ 多个本质不同的砝码. 

考虑对每个背包进行状态的压缩:写成若干个砝码大小乘积的形式. 

即 $v[i]=w[i]*a+w[i+1]*b+....$   

然后,将所有背包的系数加和 (有点类似于不进位的进制)

因为呢,你发现两个是不能拼成更大的背包的,所以只能在原有的位置上累加. 

根据贪心,我们一定优先装更小的物品. 

如果这一位有值,直接在这一位上拿一个即可,否则就要从高位借一个,然后给之间每一位的系数都累加一下.   

code: 

#include <bits/stdc++.h>
using namespace std;
void setIO(string s)
{
    string in=s+".in";
    freopen(in.c_str(),"r",stdin);
}
int n,m,len,ans;
int bas[52],w[100010],v[100010],c[52];
int main()
{
    // setIO("input");
    int i,j;
    scanf("%d%d",&n,&m);
    for(i=1;i<=n;++i)      scanf("%d",&w[i]);
    for(i=1;i<=m;++i)      scanf("%d",&v[i]);
    sort(v+1,v+1+m);
    for(i=1;i<=m;++i)
    {
        if(v[i]>bas[len]) bas[++len]=v[i];
        v[i]=len;
    }
    for(i=1;i<=n;++i)    for(j=len;j;--j) c[j]+=w[i]/bas[j],w[i]%=bas[j];
    for(i=1;i<=m;++i)
    {
        if(c[v[i]]) c[v[i]]--,ans++;
        else
        {
            for(j=v[i];j<=len;++j)
            {
                if(c[j])
                {
                    --c[j];
                    break;
                }
                else
                {
                    c[j]=bas[j+1]/bas[j]-1;
                }
            }
            if(j>len)      break;
            else     ++ans;
        }
    }
    printf("%d\n",ans);
    return 0;
}

  

01-06 22:50