题意
暴力显然是考虑n次多重背包。
考虑假如没有(d_i)的限制,那么这实际上就是一个普通的完全背包预处理,最后(O(1))输出。
现在假设只有(c_1)这种硬币有限制,那么实际上我们只需要输出(f_m-f_{m-(d_1+1)*c_1})就好了。因为既然(c_1)这种货币使用超过了限制,那么它必定使用了大于等于(d_1+1)次,也就是说我们先取出(d_1+1)个(c_1)货币,剩下的容量随便装都是不合法的,那么不合法的方案数就是(f_{m-(d_1+1)*c_1})。
现在我们可能不止有一种硬币超出了限制,那么我们可以容斥一下,这样每次询问就可以(2^4)解决了。
code:
#include<bits/stdc++.h>
using namespace std;
const int maxn=1010;
const int maxm=100010;
int n,m;
int c[5],d[5];
long long ans;
long long f[maxm];
void dfs(int now,int sum,int k)
{
if(sum<0) return;
if(now==5)
{
if(k&1) ans-=f[sum];
else ans+=f[sum];
return;
}
dfs(now+1,sum-(d[now]+1)*c[now],k+1);
dfs(now+1,sum,k);
}
int main()
{
for(int i=1;i<=4;i++) scanf("%d",&c[i]);
scanf("%d",&n);
f[0]=1;
for(int i=1;i<=4;i++)
for(int j=c[i];j<=maxm;j++)
f[j]+=f[j-c[i]];
while(n--)
{
ans=0;
for(int i=1;i<=4;i++) scanf("%d",&d[i]);
scanf("%d",&m);
dfs(1,m,0);
printf("%lld
",ans);
}
return 0;
}