1042: [HAOI2008]硬币购物
Time Limit: 10 Sec Memory Limit: 162 MB
Submit: 2518 Solved: 1512
[Submit][Status][Discuss]
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
Sample Output
4
27
HINT
Source
【分析】
感觉这类容斥比较奇葩。
可能是脑回路得绕一下吧…
【代码】
//bzoj 1042 [HAOI2008]硬币购物
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
#define M(a) memset(a,0,sizeof a)
#define fo(i,j,k) for(i=j;i<=k;i++)
using namespace std;
const int mxn=100005;
int n,T,s;
ll dp[mxn];
int c[5],d[5];
int main()
{
int i,j,k;
fo(i,1,4)
scanf("%d",&c[i]);
dp[0]=1;
fo(k,1,4)
fo(i,c[k],100000)
dp[i]+=dp[i-c[k]];
scanf("%d",&T);
while(T--)
{
ll ans=0;
fo(i,1,4)
scanf("%d",&d[i]);
scanf("%d",&s);
ans=dp[s];
fo(i,1,4) if(s>=(d[i]+1)*c[i])
ans-=dp[s-(d[i]+1)*c[i]];
fo(i,1,4) fo(j,i+1,4) if(s>=(d[i]+1)*c[i]+(d[j]+1)*c[j])
ans+=dp[s-(d[i]+1)*c[i]-(d[j]+1)*c[j]];
fo(i,1,4) fo(j,i+1,4) fo(k,j+1,4) if(s>=(d[i]+1)*c[i]+(d[j]+1)*c[j]+(d[k]+1)*c[k])
ans-=dp[s-(d[i]+1)*c[i]-(d[j]+1)*c[j]-(d[k]+1)*c[k]];
if(s>=(d[1]+1)*c[1]+(d[2]+1)*c[2]+(d[3]+1)*c[3]+(d[4]+1)*c[4])
ans+=dp[s-(d[1]+1)*c[1]-(d[2]+1)*c[2]-(d[3]+1)*c[3]-(d[4]+1)*c[4]];
printf("%lld\n",ans);
}
return 0;
}