#容斥,完全背包#洛谷 1450 [HAOI2008]硬币购物
分析
直接多重背包应该会T掉,考虑硬币的种类比较少。
如果没有硬币数量的限制直接完全背包就可以了,
不然如果限制了硬币的数量那么第 \(d+1\) 次取这个硬币就不合法,
所以要减去 \(dp[s-c*(d+1)]\),考虑不重不漏,那么容斥一下就可以了
代码
#include <cstdio>
#include <cctype>
using namespace std;
const int N=100011;
typedef long long lll;
lll dp[N],w[4],b[4],m,ans;
int iut(){
int ans=0; char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
return ans;
}
void print(lll ans){
if (ans>9) print(ans/10);
putchar(ans%10+48);
}
int main(){
for (int i=0;i<4;++i) w[i]=iut();
dp[0]=1;
for (int i=0;i<4;++i)
for (int j=w[i];j<=N-11;++j)
dp[j]+=dp[j-w[i]];
for (int T=iut();T;--T){
for (int i=0;i<4;++i) b[i]=iut();
m=iut(),ans=0;
for (int i=0;i<16;++i){
int now=m,F=1;
for (int j=0;j<4;++j)
if ((i>>j)&1) now-=w[j]*(b[j]+1),F=-F;
if (now>=0) ans+=F*dp[now];
}
print(ans),putchar(10);
}
return 0;
}