[Luogu P1450] [BZOJ 1042] [HAOI2008]硬币购物

洛谷传送门
BZOJ传送门

题目描述

硬币购物一共有 4 4 4种硬币。面值分别为 c 1 , c 2 , c 3 , c 4 c_1,c_2,c_3,c_4 c1,c2,c3,c4。某人去商店买东西,去了 t o t tot tot次。每次带 d i d_i di c i c_i ci硬币,买 s i s_i si的价值的东西。请问每次有多少种付款方法。

输入输出格式

输入格式:

第一行 c 1 , c 2 , c 3 , c 4 , t o t c_1,c_2,c_3,c_4,tot c1,c2,c3,c4,tot 下面 t o t tot tot d 1 , d 2 , d 3 , d 4 , s d_1,d_2,d_3,d4,s d1,d2,d3,d4,s

输出格式:

每次的方法数

输入输出样例

输入样例#1:
1 2 5 10 2
3 2 3 1 10
1000 2 2 2 900
输出样例#1:
4
27

说明

d i , s ≤ 100000 d_i,s\le 100000 di,s100000

t o t &lt; 1000 tot&lt;1000 tot<1000

解题分析

先预处理出无限制的情况, 然后钦定先选 d i + 1 d_i+1 di+1枚, 剩下的所有方案都是不满足的, 减去即可。

这样搞会算重, 多减去既选 d i + 1 d_i+1 di+1 c i c_i ci d i + 1 + 1 d_{i+1}+1 di+1+1 c i + 1 c_{i+1} ci+1这类情况, 因此我们容斥掉即可。

代码如下:

#include <cstdio>
#include <cctype>
#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <cctype>
#define R register
#define IN inline
#define W while
#define gc getchar()
#define ll long long
#define MX 100500
template <class T>
IN void in(T &x)
{
	x = 0; R char c = gc;
	for (; !isdigit(c); c = gc);
	for (;  isdigit(c); c = gc)
	x = (x << 1) + (x << 3) + c - 48;
}
ll sum[MX << 1], ans;
int c[5], tot, d[5], mon;
void DFS(R int now, R int typ, R int inc)
{
	if(inc > mon) return;
	if(now == 5) return ans += inc ? typ * sum[mon - inc] : 0, void();
	DFS(now + 1, typ, inc);
	DFS(now + 1, typ * -1, inc + c[now] * (d[now] + 1));
}
int main(void)
{
	sum[0] = 1;
	in(c[1]), in(c[2]), in(c[3]), in(c[4]), in(tot);
	for (R int i = 0; i <= 100000; ++i) sum[i + c[1]] += sum[i];
	for (R int i = 0; i <= 100000; ++i) sum[i + c[2]] += sum[i];
	for (R int i = 0; i <= 100000; ++i) sum[i + c[3]] += sum[i];
	for (R int i = 0; i <= 100000; ++i) sum[i + c[4]] += sum[i];
	W (tot--)
	{
		in(d[1]), in(d[2]), in(d[3]), in(d[4]), in(mon);
		ans = sum[mon];
		DFS(1, 1, 0);
		printf("%lld\n", ans);
	}
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值