DP(正解完全背包+容斥)
DP
Time Limit:10000MS Memory Limit:165888KB 64bit IO Format:%lld & %llu
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 //背包问题,容斥原理
//不得不说这是个好题,背包问题应该都会,主要是这个容斥原理,要理解,举个例子说明下日常中经常遇到的这个定理 一次考试,某班有15人数学得满分,有12人语文得满分,并且有4人语、数都是满分,那么这个班至少有一门得满分的同学有多少人?
答案:15+12-4=23 思路是,首先不限制4种钱币的个数,看组成某个价格的方案数共有多少
然后借助容斥定理减去4种钱币超过个数限制的情况,就不多不少的求出答案
dp[i]表示了|不限制| 硬币数目的最多付款方法,怎么转移应该都会
那么只需将
dp[res]
-d1超过的限制数 - d2超过的... - d3... - d4...
+ (d1与d2) + ... + (d3与d4)
- (d1,d2,d3)
+ (d1+d2+d3+d4)
就行了
如果还不理解再继续看
这题的运用容斥定理,看了篇博客,例子写的很好,不然我真不太好理解,尤其是 d[i]++ 是为什么
我们来理解 x = dp[s]-dp[s-(d1+1)*c1] 的含义:
x 表示 c1 硬币的数量不超过 d1 个而其他三种硬币的数量不限制拼成 s 的方案数。
我们举着例子来说明,假设现在有两种硬币,面值分别为1和2,
那么我们求出 dp: dp[0]=1 , dp[1]=1 , dp[2]=2 , dp[3]=2 , dp[4]=3 , dp[5]=3 , dp[6]=4 。
其中dp[3]的两种分别为 3 = 1+1+1 = 1+2 ,dp[6]的四种为: 6 = 1+1+1+1+1+1 = 1+1+1+1+2 = 1+1+2+2 = 2+2+2
假如我们现在求第一种硬币最多使用两个,第二种硬币无限制的方案数,按照我们说的 x = dp[6]-dp[6--(2+1)*1]=dp[6]-dp[3]=2。
也就是 6 = 1+1+2+2 = 2+2+2 两种。发现删除了 1+1+1+1+1+1 和 1+1+1+1+2 两种情况,
为什么能够通过减去 dp[3] 删掉这两种?我们来看 dp[3], 3 = 1+1+1 = 1+2 ,
d1+1 就是相当于用掉了 di 个硬币,所以 dp[3] 的情况要从答案中剔除
先来易懂的用for容斥的代码
#include <iostream>
#include <stdio.h>
using namespace std; typedef long long LL;
#define MAX 100005 LL c[],d[];
LL dp[MAX];
LL ans; int main()
{
for (int i=;i<=;i++)
scanf("%lld",&c[i]);
int tot;
scanf("%lld",&tot);
dp[]=;
for (int i=;i<=;i++)
for (int j=c[i];j<=;j++)
dp[j]+=dp[j-c[i]];
while (tot--)
{
LL res;
for (int i=;i<=;i++)
{
scanf("%lld",&d[i]);
d[i]++;
} scanf("%lld",&res);
ans=dp[res]; int i,j,k;
for (i=;i<=;i++)
if (res>=c[i]*d[i])
ans-=dp[res-c[i]*d[i]]; for (i=;i<=;i++)
for (j=i+;j<=;j++)
if (res>=c[i]*d[i]+c[j]*d[j])
ans+=dp[res-c[i]*d[i]-c[j]*d[j]];
for (i=;i<=;i++)
for (j=i+;j<=;j++)
for (k=j+;k<=;k++)
if (res>=c[i]*d[i]+c[j]*d[j]+c[k]*d[k])
ans-=dp[res-c[i]*d[i]-c[j]*d[j]-c[k]*d[k]];
if (res>=c[]*d[]+c[]*d[]+c[]*d[]+c[]*d[])
ans+=dp[res-c[]*d[]-c[]*d[]-c[]*d[]-c[]*d[]]; printf("%lld\n",ans); }
return ;
}
这个是DFS去处理容斥,简洁明了,时间是一样的
#include <iostream>
#include <stdio.h>
using namespace std; typedef long long LL;
#define MAX 100005 LL c[],d[];
LL dp[MAX];
LL ans; void dfs(int x,int k,LL s)
{
if (s<)return;
if (x==)
{
if (k%)ans-=dp[s];
else ans+=dp[s];
return;
}
dfs(x+,k+,s-(d[x]+)*c[x]);
dfs(x+,k,s);
}
int main()
{
for (int i=;i<=;i++)
scanf("%lld",&c[i]);
int tot;
scanf("%lld",&tot);
dp[]=;
for (int i=;i<=;i++)
for (int j=c[i];j<=;j++)
dp[j]+=dp[j-c[i]]; while (tot--)
{
LL res;
for (int i=;i<=;i++)
scanf("%lld",&d[i]); scanf("%lld",&res);
ans= ;
dfs(,,res);
printf("%lld\n",ans);
}
return ;
}
DP(正解完全背包+容斥)的更多相关文章
- Luogu-P1450 [HAOI2008]硬币购物-完全背包+容斥定理
Luogu-P1450 [HAOI2008]硬币购物-完全背包+容斥定理 [Problem Description] 略 [Solution] 上述题目等价于:有\(4\)种物品,每种物品有\(d_i ...
- 洛谷P1450 [HAOI2008]硬币购物 背包+容斥
无限背包+容斥? 观察数据范围,可重背包无法通过,假设没有数量限制,利用用无限背包 进行预处理,因为实际硬币数有限,考虑减掉多加的部分 如何减?利用容斥原理,减掉不符合第一枚硬币数的,第二枚,依次类推 ...
- P1450 [HAOI2008]硬币购物(完全背包+容斥)
P1450 [HAOI2008]硬币购物 暴力做法:每次询问跑一遍多重背包. 考虑正解 其实每次跑多重背包都有一部分是被重复算的,浪费了大量时间 考虑先做一遍完全背包 算出$f[i]$表示买价值$i$ ...
- BZOJ-1042:硬币购物(背包+容斥)
题意:硬币购物一共有4种硬币.面值分别为c1,c2,c3,c4.某人去商店买东西,去了tot次.每次带di枚ci硬币,买si的价值的东西.请问每次有多少种付款方法. 思路:这么老的题,居然今天才做到. ...
- BZOJ 1042 [HAOI2008]硬币购物(完全背包+容斥)
题意: 4种硬币买价值为V的商品,每种硬币有numi个,问有多少种买法 1000次询问,numi<1e5 思路: 完全背包计算出没有numi限制下的买法, 然后答案为dp[V]-(s1+s2+s ...
- P4707-重返现世【dp,数学期望,扩展min-max容斥】
正题 题目链接:https://www.luogu.com.cn/problem/P4707 题目大意 \(n\)个物品,每次生成一种物品,第\(i\)个被生成的概率是\(\frac{p_i}{m}\ ...
- BZOJ1042 [HAOI2008]硬币购物 【完全背包 + 容斥】
1042: [HAOI2008]硬币购物 Time Limit: 10 Sec Memory Limit: 162 MB Submit: 2924 Solved: 1802 [Submit][St ...
- [LOJ#3119][Luogu5405][CTS2019]氪金手游(DP+容斥)
先考虑外向树的做法,显然一个点在其子树内第一个出现的概率等于它的权值除以它子树的权值和.于是f[i][j]表示i的子树的权值和为j时,i子树内所有数的相互顺序都满足条件的概率,转移直接做一个背包卷积即 ...
- 知识点简单总结——minmax容斥
知识点简单总结--minmax容斥 minmax容斥 好像也有个叫法叫最值反演? 就是这样的一个柿子: \[max(S) = \sum\limits_{ T \subseteq S } min(T) ...
随机推荐
- Myeclipse 编译等级
1.Java compiler level does not match the version of the installed Java project facet. 问题描述:编译等级不匹配 解 ...
- Convert WebP to PNG using java
WebP是谷歌的图片格式,java 类库imageio 是不支持此种格式的.眼下除了在线转换以及工具以外,第三方类库转换webp格式大致有: 1.linux:Google libwebp 既是类库也能 ...
- Android源代码下载
清华大学AOSP镜像: https://mirrors.tuna.tsinghua.edu.cn/help/AOSP/
- 倍福TwinCAT(贝福Beckhoff)基础教程3.1 TwinCAT如何编写简单的计算器
把编写简单计算器作为入门的第一个范例程序,主要是因为比较简单,而且综合了HMI,数据类型,数据转换,PRG和FBD等功能块的混合等知识,个人认为还是比较适合用来快速上手的.由于是第一个范例,所以视频教 ...
- Solidworks如何在自定义的基准面上创建3D草图
1 选择某个基准面 右击"基准面上的3D草图" 2 当基准面出现黄色框即为正确.
- 关于ionic打包出错:ionic Unable to start the daemon process
一直试都没问题的ionic build android 今天竟然冒出了这个错误 Error:Unable to start the daemon process. This problem migh ...
- react-native fetch 请求封装
1.fetch 函数封装 fetch.js /** * 请求头 * @type {{Accept: string, Content-Type: string}} */ const header = { ...
- Mybatis 批量插入数据
--mybatis 批量插入数据 --1.Oracle(需要测试下是否支持MySQL) < insert id ="insertBatch" parameterType=&q ...
- 阿里CI/CD、DevOps、分层自动化技术
原文地址:http://www.infoq.com/cn/news/2017/01/alibaba-yunxiao-cicd-devops 在互联网时代,产品快速迭代的重要性不言而喻.不管是传统企业还 ...
- 改变listview中item选中时文字的颜色
摘要 当listview的某个item选中时,默认有个选中的高亮显示,如果你要自定义选中时的高亮显示效果,可以在listview中设置属性 android:listSelector="@dr ...