我们可以先预处理出完全背包时的方案数
现在考虑不合法的方案数,如果超过了d[i]个,那么就减去(d[i]+1)*c[i]个,那么意思就是现在从dp[0]开始,无论我怎么选,他都是不合法的。
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
#define LL long long
using namespace std;
const int maxn=1e5+10;
LL c[10],dp[maxn+10];
LL d[maxn+10];
int main()
{
for(int i=0;i<4;i++)
{
scanf("%lld",&c[i]);
}
dp[0]=1;
for(int i=0;i<4;i++)
{
for(int j=c[i];j<=maxn;j++)dp[j]+=dp[j-c[i]];
}
int m;
scanf("%d",&m);
LL sum;
while(m--)
{
for(int i=0;i<4;i++)scanf("%lld",&d[i]);
scanf("%lld",&sum);
LL s1,ans;
ans=dp[sum];
for(int i=1;i<16;i++)
{
s1=sum;
int cnt=0;
for(int j=0;j<4;j++)
{
if(i&(1<<j))s1-=(d[j]+1)*c[j],cnt++;
}
if(s1<0)continue;
if(cnt%2)ans-=dp[s1];
else ans+=dp[s1];
}
printf("%lld\n",ans);
}
return 0;
}