【bzoj1042】[HAOI2008]硬币购物
首先使用DP预处理,先求出,在不考虑每种硬币个数的限制的情况下,每个钱数有多少种拼凑方案。
为了避免重复的方案被转移,所以我们以硬币种类为第一层循环,这样阶段性的增加硬币。
一定要注意这个第一层循环要是硬币种类,并且初始 f[0] = 1。
之后对于每个询问 (A1, A2, A3, A4, S) ,根据容斥原理,我们要求的答案 Ans 就是 f[S] - (硬币1超限制的方案数) - (硬币2超限制的方案数) - (硬币3超限制的方案数) - (硬币4超限制的方案数) + (硬币1,2超限制的方案数) + (硬币1,3超限制的方案数) + (硬币1,4超限制的方案数) + .... - (硬币1,2,3超限制的方案数) - ... + (硬币1,2,3,4超限制的方案数) 。
怎样求硬币1超限制的方案数呢?我们只要先固定取 (A1+1) 个硬币1,剩余的钱数随便取就可以了,就是 f[S - (A1+1) * V[1]] 。
其余的情况都类似。
容斥的部分使用搜索实现。
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<queue>
using namespace std; #define MAXN 100010 typedef long long LL; int n;
int x;
int a[7],b[7]; LL ans; LL f[MAXN]; void dfs(int x,int k,int d)
{
if (d<0)
return ;
if (x==5)
{
if (k & 1)
ans-=f[d];
else
ans+=f[d];
return ;
}
dfs(x+1,k+1,d-(a[x]+1)*b[x]);
dfs(x+1,k,d);
} int main()
{
for (int i=1;i<=4;i++)
scanf("%d",&b[i]);
scanf("%d",&n);
f[0]=1;
for (int i=1;i<=4;i++)
for (int j=b[i];j<=MAXN;j++)
f[j]+=f[j-b[i]];
for (int i=1;i<=n;i++)
{
for (int j=1;j<=4;j++)
scanf("%d",&a[j]);
scanf("%d",&x);
ans=0;
dfs(1,0,x);
printf("%lld\n",ans);
}
return 0;
}
还有一个鬼畜算法。。搞不清楚啊。。
用容斥原理做背包。
首先,我们要先处理出四种钞票都不限的方案数。
对于每一个询问,我们利用容斥原理,答案为:得到S所有超过数量限制的方案数-硬币1超过限制的方案数-硬币2超过限制的方案数-硬币3超过限制的方案数-硬币4超过限制的方案数+硬币1、2超过限制的方案数+…+硬币1、2、3、4均超过限制的方案数。
而对于每种方案数的求法,也非常简单:假设我们要求的是F[S],则硬币1超过限制(即硬币1取的个数≥d[1]+1,不考虑硬币2、3、4是否超过限制)时的方案数即为F[S-(d[1]+1)×c[1]]。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int c[5];
long long F[110000];
struct{long long operator[](int pos){return pos<0?0:F[pos];}}f;
int main(int argc, char *argv[])
{
int T;scanf("%d%d%d%d%d",&c[1],&c[2],&c[3],&c[4],&T);
F[0]=1;
for(int i=1;i<=4;i++)
for(int j=0;j<=100000;j++)
if(j+c[i]<=100000)F[j+c[i]]+=F[j];
while(T--)
{
int d[5],s;scanf("%d%d%d%d%d",&d[1],&d[2],&d[3],&d[4],&s);
long long ans=f[s];
ans-=f[s-(d[1]+1)*c[1]];
ans-=f[s-(d[2]+1)*c[2]];
ans-=f[s-(d[3]+1)*c[3]];
ans-=f[s-(d[4]+1)*c[4]];
ans+=f[s-(d[1]+1)*c[1]-(d[2]+1)*c[2]];
ans+=f[s-(d[1]+1)*c[1]-(d[3]+1)*c[3]];
ans+=f[s-(d[1]+1)*c[1]-(d[4]+1)*c[4]];
ans+=f[s-(d[2]+1)*c[2]-(d[3]+1)*c[3]];
ans+=f[s-(d[2]+1)*c[2]-(d[4]+1)*c[4]];
ans+=f[s-(d[3]+1)*c[3]-(d[4]+1)*c[4]];
ans-=f[s-(d[1]+1)*c[1]-(d[2]+1)*c[2]-(d[3]+1)*c[3]];
ans-=f[s-(d[1]+1)*c[1]-(d[2]+1)*c[2]-(d[4]+1)*c[4]];
ans-=f[s-(d[1]+1)*c[1]-(d[3]+1)*c[3]-(d[4]+1)*c[4]];
ans-=f[s-(d[2]+1)*c[2]-(d[3]+1)*c[3]-(d[4]+1)*c[4]];
ans+=f[s-(d[1]+1)*c[1]-(d[2]+1)*c[2]-(d[3]+1)*c[3]-(d[4]+1)*c[4]];
#ifdef ONLINE_JUDGE
printf("%lld\n",ans);
#else
printf("%I64d\n",ans);
#endif
}
return 0;
}
【bzoj1042】[HAOI2008]硬币购物的更多相关文章
- BZOJ1042 [HAOI2008]硬币购物 【完全背包 + 容斥】
1042: [HAOI2008]硬币购物 Time Limit: 10 Sec Memory Limit: 162 MB Submit: 2924 Solved: 1802 [Submit][St ...
- BZOJ1042 [HAOI2008]硬币购物 完全背包 容斥原理
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1042 题目概括 硬币购物一共有4种硬币.面值分别为c1,c2,c3,c4.某人去商店买东西,去了t ...
- [bzoj1042][HAOI2008][硬币购物] (容斥原理+递推)
Description 硬币购物一共有4种硬币.面值分别为c1,c2,c3,c4.某人去商店买东西,去了tot次.每次带di枚ci硬币,买si的价值的东西.请问每次有多少种付款方法. Input 第一 ...
- bzoj1042: [HAOI2008]硬币购物
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #i ...
- BZOJ1042:[HAOI2008]硬币购物(DP,容斥)
Description 硬币购物一共有4种硬币.面值分别为c1,c2,c3,c4.某人去商店买东西,去了tot次.每次带di枚ci硬币,买si的价值的东西.请问每次有多少种付款方法. Input 第一 ...
- BZOJ1042 HAOI2008硬币购物(任意模数NTT+多项式求逆+生成函数/容斥原理+动态规划)
第一眼生成函数.四个等比数列形式的多项式相乘,可以化成四个分式.其中分母部分是固定的,可以多项式求逆预处理出来.而分子部分由于项数很少,询问时2^4算一下贡献就好了.这个思路比较直观.只是常数巨大,以 ...
- 2019.02.09 bzoj1042: [HAOI2008]硬币购物(完全背包+容斥原理)
传送门 题意简述:有四种面值的硬币,现在qqq次询问(q≤1000)(q\le1000)(q≤1000),每次给出四种硬币的使用上限问最后刚好凑出sss块钱的方案数(s≤100000)(s\le100 ...
- bzoj1042: [HAOI2008]硬币购物(DP+容斥)
1600+人过的题排#32还不错嘿嘿 浴谷夏令营讲过的题,居然1A了 预处理出f[i]表示购买价值为i的东西的方案数 然后每次询问进行一次容斥,答案为总方案数-第一种硬币超限方案-第二种超限方案-第三 ...
- 【BZOJ1042】[HAOI2008]硬币购物 容斥
[BZOJ10492][HAOI2008]硬币购物 Description 硬币购物一共有4种硬币.面值分别为c1,c2,c3,c4.某人去商店买东西,去了tot次.每次带di枚ci硬币,买si的价值 ...
- 【BZOJ-1042】硬币购物 容斥原理 + 完全背包
1042: [HAOI2008]硬币购物 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1811 Solved: 1057[Submit][Stat ...
随机推荐
- 2.10.4 aside元素
aside元素 <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> < ...
- MRC转ARC
转载请注明出处:http://blog.csdn.net/cywn_d/article/details/18222671 1.删除所有retain,release和autorelease. 2.把原来 ...
- js 实现弹力球效果
1.html代码: <div id='imgid'> <img src="img/5.png"> </div> 2.js代码: imgobj=d ...
- hdu 1792 A New Change Problem(互质数之间最大不能组合数和不能组合数的个数)
题意:求互质的m和n的最大不能组合数和不能组合数的个数 思路:m和n的最大不能组合数为m*n-m-n,不能组合数的个数为(m-1)*(n-1)/2 推导: 先讨论最大不能组合数 因为gcd(m,n)= ...
- 【thinking in java】反射
前言 反射是框架设计的灵魂,使用的前提条件:必须先得到字节码的Class,Class类用于表示字节码,字节码即是.class文件 概述 JAVA反射机制:在程序运行的过程中,对于任意一个类,都可以知道 ...
- centos7安装kvm虚拟机
一 centos7安装kvm虚拟机 1.验证CPU是否支持KVM 结果中有vmx(Intel)或svm(AMD)字样,就说明CPU的支持的. [root@centos ~]# egrep '(vmx| ...
- AutoEncoders原理
目录 Auto-Encoders How to Train? Auto-Encoders How to Train?
- LeetCode 122. Best Time to Buy and Sell Stock II (stock problem)
Say you have an array for which the ith element is the price of a given stock on day i. Design an al ...
- jar项目 BeanDefinitionParsingException: Configuration problem:Unable to locate Spring NamespaceHandler for XML schema namespace
最近由于项目需要,需要jar项目来处理. 我在项目中整合了Spring,在编辑器中启动没有问题,但是使用ant打包为一个完整jar文件,部署后启动报错如下 org.springframework.be ...
- Java面向对象学习-----类的成员变量
类的成员变量: 猜数字游戏:一个类A有一个成员变量v,通过随机产生一个100内的整数给v赋值.定义一个方法,对A类的成员变量v进行猜. 没有猜对的情况下提示如果大了则提示大了,小了则提示小了,并且 ...