题目大意:共有4种硬币,面值分别为c1,c2,c3,c4。某人去商店买东西,去了tot次。每次带di枚ci硬币,买s的价值的东西。请问每次有多少种付款方法
题解:容斥原理
设f[i]为不考虑数量限制时得到面值i的方案数(完全背包)
由容斥原理,ans=价值为s时的方案数(超过限制)−∑(一种硬币超过限制)+∑(两种硬币超过限制)−∑(三种硬币超过限制)……
当硬币x超过限制时,至少使用了d[x]+1个x,于是总费用减去(d[x]+1)∗c[x]
一共只有24种情况,可以用dfs或者二进制枚举
我的收获:不太会容斥啊……
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
int n,S,T,c[5],d[5];
long long ans,f[100005];
void First()
{
f[0]=1;
for(int i=1;i<=4;i++)
for(int j=c[i];j<=100000;j++)
f[j]+=f[j-c[i]];
}
void Dfs(int x,int k,int sum)
{
if(sum<0) return;
if(x==5){
if(k&1) ans-=f[sum];
else ans+=f[sum];
return;
}
Dfs(x+1,k+1,sum-(d[x]+1)*c[x]);
Dfs(x+1,k,sum);
}
void work()
{
First();
while(T--){
for(int i=1;i<=4;i++) scanf("%d",&d[i]);
scanf("%d",&S);
ans=0;Dfs(1,0,S);
printf("%lld\n",ans);
}
}
void init()
{
for(int i=1;i<=4;i++) scanf("%d",&c[i]);
cin>>T;
}
int main()
{
init();
work();
return 0;
}