您的位置:首页 > 其它

BZOJ 1042: [HAOI2008]硬币购物

2014-09-01 12:45 357 查看
题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1042

我是用多重背包水过的。。。正解是用容斥原理,枚举被限制的硬币。。。。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <stack>
#include <string.h>
#include <queue>
#include <vector>
#include <algorithm>
#include <cassert>
#include <set>
#include <map>
#include <cmath>
#include <ctime>
using namespace std;
#define rep(i,a,b) for(int i=(a);i<(b);++i)
#define rrep(i,a,b) for(int i=(a);i>=(b);--i)
#define clr(a,x) memset(a,(x),sizeof(a))
#define eps 1e-8
#define LL long long
#define mp make_pair
const int maxn=100000+5;
LL dp[maxn],tem[maxn];
LL sum[maxn];

inline void multipack(int amt,int cost,int n)
{
if(amt==0) return;
rep(i,0,cost) tem[i]=sum[i]=dp[i];
int k=0;
rep(i,cost,n+1) {
tem[i]=dp[i];
if(k>=cost)  k -= cost;
sum[k] += dp[i];
if(i-(amt+1)*cost>=0) sum[k] -= tem[i-(1+amt)*cost];
dp[i] = sum[k];
++k;
}
}

int c[5],d[5];
int main()
{
// freopen("in.txt","r",stdin);
int tot;
while(scanf("%d%d%d%d%d",c,c+1,c+2,c+3,&tot)==5) {
while(tot--) {
int s;
scanf("%d%d%d%d%d",d,d+1,d+2,d+3,&s);
memset(dp,0,sizeof(LL)*(s+2));
dp[0]=1;
rep(i,0,4) multipack(d[i],c[i],s);
printf("%lld\n",dp[s]);
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: