题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1042

dp预处理+容斥原理。

先预处理求出无限制的各面值的组成方案数 f (完全背包)。

求s [ i ]有限制的,就是s [ i ]无限制方案数 - 单种硬币一定超过限制的方案数 + 两种的 - 三种的 + 四种的。

第 k 中硬币一定超过限制的方案数就是f [ s [ i ] - c [ k ] * ( d [ k ] + 1 ) ],即确定用了 d + 1 个该硬币,刨去它们后的无限制方案数。

当 c [ k ] * ( d [ k ] + 1 ) > s [ i ] 时不用操作,即没有“超过该限制”的可能。但== s [ i ] 时还是要操作的,f [ 0 ] = 1。

以为要用高精度,结果WA。看看题解发现不用高精度,于是……

如果高精度的话,防止某次减到了负数,可以先把加的弄了(反正只有四种硬币)。

非高精AC代码:

#include<iostream>
#include<cstdio>
using namespace std;
typedef long long ll;
ll c[],d[][],tot,mx,s[],f[],ans;
void pre()
{
f[]=;///
for(int i=;i<=;i++)
for(ll j=c[i];j<=mx;j++)
f[j]+=f[j-c[i]];
}
void dfs(ll now,ll k,ll cnt,ll z)//第now次询问,第k号,选了cnt个,f目前脚标
{
if(z<)return;//不是z<=0!!
if(k==)
{
if(cnt&)ans-=f[z];
else if(cnt)ans+=f[z];
return;
}
dfs(now,k+,cnt,z);
dfs(now,k+,cnt+,z-c[k]*d[now][k]-c[k]);
}
int main()
{
for(int i=;i<=;i++)scanf("%lld",&c[i]);
scanf("%lld",&tot);
for(int i=;i<=tot;i++)
scanf("%lld%lld%lld%lld%lld",&d[i][],&d[i][],&d[i][],&d[i][],&s[i]),mx=max(mx,s[i]);
pre();
for(int i=;i<=tot;i++)
{
ans=f[s[i]];
dfs(i,,,s[i]);
printf("%lld\n",ans);
}
return ;
}

高精WA代码:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long ll;
const int INF=;
ll c[],d[][],tot,s[],mx,tp;
int f[INF][],ans[];
void plu(ll k,int a[],int b[])
{
int tmp[]={},lm=max(a[],b[]);
for(int i=;i<=lm;i++)
{
tmp[i]+=a[i]+b[i];
if(tmp[i]>)tmp[i]-=,tmp[i+]++;
}
tmp[]=lm;
if(tmp[tmp[]+])tmp[]++;
memcpy(f[k],tmp,sizeof tmp);
}
void pre()
{
f[][]=;f[][]=;
for(int i=;i<=;i++)
for(ll j=c[i];j<=mx;j++)
plu(j,f[j],f[j-c[i]]);
}
void print()
{
// printf("(%d)",ans[0]);
for(int i=ans[];i;i--)
printf("%d",ans[i]);
printf("\n");
}
void plu2(ll k)
{
int lm=max(ans[],f[k][]);
for(int i=;i<=lm;i++)
{
ans[i]+=f[k][i];
if(ans[i]>)ans[i]-=,ans[i+]++;
}
if(ans[ans[]+])ans[]++;
// printf("++ k=%d ",k);print();
}
void jian(ll k)
{
// int lm=max(ans[0],f[k][0]);
for(int i=;i<=f[k][];i++)
{
ans[i]-=f[k][i];
if(ans[i]<)ans[i]+=,ans[i+]--;
}
while(!ans[ans[]]&&ans[]>)ans[]--;
// printf("-- k=%d ",k);print();
}
//void debugprint()
//{
// for(int i=1;i<=s[1];i++)
// {
// printf("i=%d ",i);
// for(int j=f[i][0];j;j--)
// printf("%d",f[i][j]);
// printf("\n");
// }
//}
int main()
{
for(int i=;i<=;i++)scanf("%lld",&c[i]);
scanf("%lld",&tot);
for(int i=;i<=tot;i++)
{
scanf("%lld%lld%lld%lld%lld",&d[i][],&d[i][],&d[i][],&d[i][],&s[i]);
mx=max(mx,s[i]);
}
pre();
for(int i=;i<=tot;i++)
{
memcpy(ans,f[s[i]],sizeof f[s[i]]);//
// debugprint();
for(int u=;u<;u++)
for(int v=u+;v<=;v++)
{
tp=c[u]*d[i][u]+c[v]*d[i][v]+c[u]+c[v];
if(tp<=s[i])plu2(s[i]-tp); ///<=!!!,因为我的f[0]有值为1 ;正是要用这个1!
}
tp=c[]*d[i][]+c[]*d[i][]+c[]*d[i][]+c[]*d[i][]+c[]+c[]+c[]+c[];
if(tp<=s[i])plu2(s[i]-tp);
for(int u=;u<=;u++)
{
tp=c[u]*d[i][u]+c[u];
if(tp<=s[i])jian(s[i]-tp);
}
for(int u=;u<=;u++)
for(int v=u+;v<=;v++)
for(int j=v+;j<=;j++)
{
tp=c[u]*d[i][u]+c[v]*d[i][v]+c[j]*d[i][j]+c[u]+c[v]+c[j];
if(tp<=s[i])jian(s[i]-tp);
}
print();
}
return ;
}

bzoj1042硬币购物的更多相关文章

  1. bzoj1042硬币购物——递推+容斥

    题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1042 递推,再用容斥原理减掉多余的,加上多减的……(dfs)即可. 代码如下: #includ ...

  2. [bzoj1042]硬币购物

    先预处理出没有上限的方案数,然后容斥,然后将所有东西的范围都变为[0,+oo),即可用预处理出的dp数组计算 1 #include<bits/stdc++.h> 2 using names ...

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

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

  4. 【BZOJ1042】硬币购物(动态规划,容斥原理)

    [BZOJ1042]硬币购物(动态规划,容斥原理) 题面 BZOJ Description 硬币购物一共有4种硬币.面值分别为c1,c2,c3,c4.某人去商店买东西,去了tot次.每次带di枚ci硬 ...

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

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

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

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

  7. bzoj1042: [HAOI2008]硬币购物

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

  8. 【BZOJ1042】【DP + 容斥】[HAOI2008]硬币购物

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

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

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

随机推荐

  1. spring cloud图形化dashboard是如何实现指标的收集展示的

    spring cloud图形化dashboard是如何实现指标的收集展示的 1.dashboard图形化界面入口 http://localhost:10000/hystrix.stream 说明:端口 ...

  2. JavaScript学习总结(一)——JavaScript基础

    一.JavaScript语言特点 1.1.JavaScript是基于对象和事件驱动的(动态的) 它可以直接对用户或客户输入做出响应,无须经过Web服务程序.它对用户的响应,是采用以事件驱动的方式进行的 ...

  3. POJ 1847 dijstra算法

    POJ 无限循环CE中.感觉是读题难.然后就可以建图上模板了. 附个人代码: #include<stdio.h>#include<string.h>#include<io ...

  4. The "Double-Checked Locking is Broken" Declaration

    双重检查锁定在延迟初始化的单例模式中见得比较多(单例模式实现方式很多,这里为说明双重检查锁定问题,只选取这一种方式),先来看一个版本: public class Singleton { private ...

  5. (C/C++学习笔记) 十三. 引用

    十三. 引用 ● 基本概念 引用: 就相当于为变量起了一个别名(alias), △与指针不同的是它不是一个数据类型 通过引用我们可以间接访问变量,指针也能间接访问变量,但引用在使用上相对指针更安全. ...

  6. 宿主环境(host environment)

    在此前的内容中,我讨论的都是JavaScript语言及其规范,而并非该语言的应用环境.在大多数人看来,JavaScript应用环境都是Web浏览器,这也的确是该语言最早的设计目标.然而从很早开始,Ja ...

  7. java正则获取括号内的数据与排除括号内的数据

    1.正则获取括号内的数据 /** * 获取指定字符串中括号内的内容,返回字符串数组 * @param content * @return */ public String[] getBracketCo ...

  8. L228 the complicated issue of equality: non-disabled actors play disabled roles

    Bryan Cranston’s defence of playing a wheelchair user in the new comedy-drama The Upside has underli ...

  9. 高并发下linux ulimit优化

    系统性能一直是一个受关注的话题,如何通过最简单的设置来实现最有效的性能调优,如何在有限资源的条件下保证程序的运作,ulimit 是我们在处理这些问题时,经常使用的一种简单手段.ulimit 是一种 l ...

  10. GTK安装

    上面是linux下GTK+配置所需要的库,关于各个库的功能,查看http://www.gtk.org/overview.php,至于库的下载在http://www.gtk.org/download/l ...