神奇的题目,dp+容斥。一开始基本没思路,看了别人的题解后才理解。
令f数组为硬币无数量限制时达到s的种类,先预处理完。
然后对于每次询问只要加出一个sum后减去重复部分。(容斥)
#include <cstdio>
#define ll long long
using namespace std;
const int N=100005;
int c[6],tot;
int d[6],s;
ll ans,f[N];
void dfs(ll now,ll k,ll sum)
{
if (sum<0) return;
if (now==5)
{
if (k&1) ans-=f[sum];
else ans+=f[sum];
return ;
}
dfs(now+1,k+1,sum-(d[now]+1)*c[now]);
dfs(now+1,k,sum);//不超限即不用减一次容斥所以k不加
}
int main()
{
register int i,j;
scanf("%d %d %d %d %d",&c[1],&c[2],&c[3],&c[4],&tot);
f[0]=1;
for (i=1;i<=4;i++)
for (j=c[i];j<=100000;j++)
{
f[j]+=f[j-c[i]];
}
for (i=1;i<=tot;i++)
{
scanf("%d %d %d %d %d",&d[1],&d[2],&d[3],&d[4],&s);
ans=0;
dfs(1,0,s);
printf("%lld\n",ans);
}
return 0;
}