首先使用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. python pandas读写excel

    import pandas as pd import numpy as np df = pd.read_csv("result.csv") # csv # df = pd.read ...

  2. zay大爷的神仙题目 D1T3-膜你抄

    依旧是外链 锦鲤抄 [题目背景] 你在尘世中辗转了千百年 却只让我看你最后一眼 火光描摹容颜燃尽了时间 别留我一人,孑然一身 凋零在梦境里面. ——银临&云の泣<锦鲤抄> [问题描 ...

  3. vuex如何管理需要即时更新的全局变量

    自己在使用vue练习开发的时候遇到全局变量无法即时更新的问题,查了资料之后得出结论使用vuex能够快速解决该问题,但是看了好多人讲解vuex的教程自己跟着去做都没解决自己想要的,最后找到一个比较容易理 ...

  4. mxnet.base.MXNetError: src/imperative/./imperative_utils.h:70: Check failed: inputs[i]->ctx().dev_mask() == ctx.dev_mask() (1 vs. 2)

    mxnet 训练错误: mxnet.base.MXNetError: [14:42:22] src/imperative/./imperative_utils.h:70: Check failed: ...

  5. jenkins构建项目记录2(tag)

    与jenkins构建项目记录1不同的是通过tag拉去对应版本代码 1.先安装创建(git parameter) 2.general设置 name可任意命名,下面源码管理设置时变量会引用到. 3.源码管 ...

  6. <input type="button" /> 和<input type="submit" /> 的区别

    <input type="button" /> 这就是一个按钮.如果你不写javascript 的话,按下去什么也不会发生.<input type="s ...

  7. LeetCode(56)Merge Intervals

    题目 Given a collection of intervals, merge all overlapping intervals. For example, Given [1,3],[2,6], ...

  8. poj 2186 强连通分量

    poj 2186 强连通分量 传送门 Popular Cows Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 33414 Acc ...

  9. css3 & background & background-image

    css3 & background & background-image https://developer.mozilla.org/en-US/docs/Web/CSS/backgr ...

  10. Linux下汇编语言学习笔记33 ---

    这是17年暑假学习Linux汇编语言的笔记记录,参考书目为清华大学出版社 Jeff Duntemann著 梁晓辉译<汇编语言基于Linux环境>的书,喜欢看原版书的同学可以看<Ass ...