首页 > 其他分享 >P1450 [HAOI2008] 硬币购物

P1450 [HAOI2008] 硬币购物

时间:2022-09-01 17:24:07浏览次数:75  
标签:P1450 硬币 容斥 https include HAOI2008

P1450 [HAOI2008] 硬币购物

已经八百年没写过题解了。

先是因为懒,后是没有时间写了。

但是这题印象属实深刻。任务列表里吃灰两个月

想到了完全背包然后容斥 bulabula 的

但是就是不知道该怎么下手。

好像也没那么复杂。

先预处理出购买价值 \(i\) 的东西的方案数,先不管限不限制个数。

然后把不合法的部分减去。

这个可以预处理出来,直接完全背包就行了。

那么什么是不合法的部分?

即要排除 \(> d_i\) 的情况,也就是 \(\geq d_i+1\) 的情况,这部分的价值是 $ s- (d_i+1)\times c_i$,之前处理出了价值 \(i\) 的方案数,那这个是直接可以搞的, 然后容斥的加减即可。

具体的容斥证明可以看 https://www.luogu.com.cn/discuss/481921

以及不是多么困难的码。

// Problem: P1450 [HAOI2008] 硬币购物
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P1450
// Memory Limit: 125 MB
// Time Limit: 1000 ms
// Author: Gym_nastics
// 
// Powered by CP Editor (https://cpeditor.org)

#include<map>
#include<cmath>
#include<queue>
#include<cstdio>
#include<vector>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<functional>
#define INF 0x3f3f3f3f
#define best cout<<"whw is a hreo\n";
#define int long long

const int mod=1e9+7;
const int maxn=1e6+7,maxm=2e3+1;

using namespace std;

inline int read(){
	int x=0,f=1;
	char ch=getchar();
	for(;ch>'9'||ch<'0';ch=getchar()) if(ch=='-') f=-1;
	for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0';
	return x*f;
}

int f[maxn+1],c[5],d[5],n; 
#define cl(x) (d[x]+1)*c[x]

signed main() {
	for(int i=0;i<4;i++) c[i]=read();
	f[0]=1;
	for(int i=0;i<4;i++)
	for(int j=c[i];j<=maxn-5;j++) f[j]+=f[j-c[i]];
	n=read();
	for(int i=1;i<=n;i++){
		for(int j=0;j<4;j++) d[j]=read();int s=read();
		int res=f[s];
		for(int j=1;j<16;j++){
			int k=0,sum=s;
			for(int l=0;l<4;l++) if(j&(1<<l)) k^=1,sum-=cl(l);
			if(sum>=0) res+=k?-f[sum]:f[sum];
		}
		printf("%lld\n",res);
	}
	return 0;
}

标签:P1450,硬币,容斥,https,include,HAOI2008
From: https://www.cnblogs.com/BlackDan/p/16647210.html

相关文章

  • 找更多硬币
    https://www.acwing.com/problem/content/description/1556/思路:01背包问题的经典模型,这不过这儿的属性是bool,表示能不能,而且要你输出方案,由于方案要字典序最小,所以Ai则......
  • P2508-[HAOI2008]圆上的整点【数学】
    正题题目链接:https://www.luogu.com.cn/problem/P2508题目大意一个在\((0,0)\)的圆心,半径为\(r\),求圆有多少个整点。\(1\leqr\leq2\times10^9\)解题思路设这个......
  • 习题4-5 换硬币
    #include<stdio.h>intmain(){intmoney,n1,n2,n5,count;/*每种硬币至少有一枚,所以本题n1,n2,n5不能=0*/count=0;scanf("%d",&money);if(......
  • 6.最少硬币问题(动态规划)
    题目描述:设有n种不同面值的硬币,各硬币的面值存于数组T[1:n]中。现要用这些面值的硬币来找钱。可以使用的各种面值的硬币个数存于数组Coins[1:n]中。对任意钱数0≤m≤2000......