标签:购物 lin main using 假设 scanf 背包 需要 ret
暴力显然是考虑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\n",ans);
}
return 0;
}
标签:购物 lin main using 假设 scanf 背包 需要 ret
原文地址:https://www.cnblogs.com/nofind/p/12152515.html