首先使用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]硬币购物的更多相关文章

  1. BZOJ1042 [HAOI2008]硬币购物 【完全背包 + 容斥】

    1042: [HAOI2008]硬币购物 Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 2924  Solved: 1802 [Submit][St ...

  2. BZOJ1042 [HAOI2008]硬币购物 完全背包 容斥原理

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1042 题目概括 硬币购物一共有4种硬币.面值分别为c1,c2,c3,c4.某人去商店买东西,去了t ...

  3. [bzoj1042][HAOI2008][硬币购物] (容斥原理+递推)

    Description 硬币购物一共有4种硬币.面值分别为c1,c2,c3,c4.某人去商店买东西,去了tot次.每次带di枚ci硬币,买si的价值的东西.请问每次有多少种付款方法. Input 第一 ...

  4. bzoj1042: [HAOI2008]硬币购物

    #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #i ...

  5. BZOJ1042:[HAOI2008]硬币购物(DP,容斥)

    Description 硬币购物一共有4种硬币.面值分别为c1,c2,c3,c4.某人去商店买东西,去了tot次.每次带di枚ci硬币,买si的价值的东西.请问每次有多少种付款方法. Input 第一 ...

  6. BZOJ1042 HAOI2008硬币购物(任意模数NTT+多项式求逆+生成函数/容斥原理+动态规划)

    第一眼生成函数.四个等比数列形式的多项式相乘,可以化成四个分式.其中分母部分是固定的,可以多项式求逆预处理出来.而分子部分由于项数很少,询问时2^4算一下贡献就好了.这个思路比较直观.只是常数巨大,以 ...

  7. 2019.02.09 bzoj1042: [HAOI2008]硬币购物(完全背包+容斥原理)

    传送门 题意简述:有四种面值的硬币,现在qqq次询问(q≤1000)(q\le1000)(q≤1000),每次给出四种硬币的使用上限问最后刚好凑出sss块钱的方案数(s≤100000)(s\le100 ...

  8. bzoj1042: [HAOI2008]硬币购物(DP+容斥)

    1600+人过的题排#32还不错嘿嘿 浴谷夏令营讲过的题,居然1A了 预处理出f[i]表示购买价值为i的东西的方案数 然后每次询问进行一次容斥,答案为总方案数-第一种硬币超限方案-第二种超限方案-第三 ...

  9. 【BZOJ1042】[HAOI2008]硬币购物 容斥

    [BZOJ10492][HAOI2008]硬币购物 Description 硬币购物一共有4种硬币.面值分别为c1,c2,c3,c4.某人去商店买东西,去了tot次.每次带di枚ci硬币,买si的价值 ...

  10. 【BZOJ-1042】硬币购物 容斥原理 + 完全背包

    1042: [HAOI2008]硬币购物 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1811  Solved: 1057[Submit][Stat ...

随机推荐

  1. pom.xml配置引用项目时不生效

    1 在项目pom.xml配置中引用项目A,但是编译时,取提数引起是B: 2 原因是:[Java Build Path - Projects] 引用的还是老的项目B,删除该引用即可解决.

  2. Elasticsearch分布式机制和document分析

    1. Elasticsearch对复杂分布式机制的透明隐藏特性 1.1)分片机制 1.2)集群发现机制 1.3)shard负载均衡 1.4)shard副本,请求路由,集群扩容,shard重分配 2.  ...

  3. Linux命令学习(6):paste合并几列文件

    如果我们有三个文件: $ cat name.txt #姓名文档 Kevin Mary Tom $ cat gender.txt #性别文档 M F M $ cat age.txt #年龄文档 我们想把 ...

  4. solr-5.3.1配置(win7 x64)

    下载solr,下载地址http://www.eu.apache.org/dist/lucene/solr/5.3.1/solr-5.3.1.zip 解压到某个目录下,这里是解压到了d盘目录下,路径:D ...

  5. Java 集合相关

    对整个体系做一个记录,并不涉及详细应用 Object类 1. 重写toString方法 System.out.println可以打印任何对象在于Object类拥有一个方法 public String ...

  6. 每周一赛(E题,广搜求方案)

    Description In this problem, you are given an integer number s. You can transform any integer number ...

  7. UvaLive 4872 Underground Cables (最小生成树)

    题意: 就是裸的最小生成树(MST), 完全图, 边长是实数. 分析: 算是复习一下MST把 方法一: prim 复杂度(n^2) #include <bits/stdc++.h> usi ...

  8. eclipse中自动生成注释

    eclipse中自动生成注释 包前缀设置的地方 注释模板设置的地方 Eclipse自动生成方法注释 快捷键 自动生成方法的注释格式,例如 /*** @param str* @return* @thro ...

  9. hihoCoder#1077 RMQ问题再临-线段树

    原题地址 终于做到线段树的题了,因为建树.更新.查询都是递归操作,所以其实挺好写的. 用数组存的树,记得MAX_NODE开成两倍叶节点数大小,否则RE啊..不要问我是怎么知道的. 代码: #inclu ...

  10. scp远程文件传输

    第一次.提示下载公钥 [root@rhel5 ~]# scp install.log root@192.168.124.129:/tmp The authenticity of host '192.1 ...