【题目描述】
Description
硬币购物一共有4种硬币。面值分别为c1,c2,c3,c4。某人去商店买东西,去了tot次。每次带di枚ci硬币,买s
i的价值的东西。请问每次有多少种付款方法。
Input
第一行 c1,c2,c3,c4,tot 下面tot行 d1,d2,d3,d4,s,其中di,s<=100000,tot<=1000
Output
每次的方法数
Sample Input
1 2 5 10 2
3 2 3 1 10
1000 2 2 2 900
3 2 3 1 10
1000 2 2 2 900
Sample Output
4
27
27
HINT
Source
【题解】 记 f[i] 表示不考虑数量限制买价值为i的物品的方案数。
由容斥原理可得 ans=f[i]-有一种越界的+有两种越界的-有三种越界的+有四种越界的
越界的的计算方法:把它在限制内的全去掉,剩下的任意。
/* --------------
user Vanisher
problem bzoj-1042
----------------*/
# include <bits/stdc++.h>
# define ll long long
# define S 100000
using namespace std;
ll read(){
ll tmp=0, fh=1; char ch=getchar();
while (ch<'0'||ch>'9'){if (ch=='-') fh=-1; ch=getchar();}
while (ch>='0'&&ch<='9'){tmp=tmp*10+ch-'0'; ch=getchar();}
return tmp*fh;
}
ll c[5],d[5],n,f[S+10],s,ans;
int main(){
c[1]=read(), c[2]=read(), c[3]=read(), c[4]=read(), n=read();
f[0]=1;
for (ll i=1; i<=4; i++)
for (ll j=c[i]; j<=S; j++)
f[j]=f[j]+f[j-c[i]];
for (ll i=1; i<=n; i++){
d[1]=read(), d[2]=read(), d[3]=read(), d[4]=read(); s=read();
ans=0;
for (ll j=0; j<(1<<4); j++){
ll now=s,ti=1;
for (ll k=1; k<=4; k++)
if ((j&(1<<(k-1)))>0) now=now-(d[k]+1)*c[k],ti=-ti;
if (now>=0) ans=ans+ti*f[now];
}
printf("%lld\n",ans);
}
return 0;
}