bzoj1042硬币购物
题目: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硬币购物的更多相关文章
- bzoj1042硬币购物——递推+容斥
题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1042 递推,再用容斥原理减掉多余的,加上多减的……(dfs)即可. 代码如下: #includ ...
- [bzoj1042]硬币购物
先预处理出没有上限的方案数,然后容斥,然后将所有东西的范围都变为[0,+oo),即可用预处理出的dp数组计算 1 #include<bits/stdc++.h> 2 using names ...
- BZOJ1042 [HAOI2008]硬币购物 完全背包 容斥原理
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1042 题目概括 硬币购物一共有4种硬币.面值分别为c1,c2,c3,c4.某人去商店买东西,去了t ...
- 【BZOJ1042】硬币购物(动态规划,容斥原理)
[BZOJ1042]硬币购物(动态规划,容斥原理) 题面 BZOJ Description 硬币购物一共有4种硬币.面值分别为c1,c2,c3,c4.某人去商店买东西,去了tot次.每次带di枚ci硬 ...
- [bzoj1042][HAOI2008][硬币购物] (容斥原理+递推)
Description 硬币购物一共有4种硬币.面值分别为c1,c2,c3,c4.某人去商店买东西,去了tot次.每次带di枚ci硬币,买si的价值的东西.请问每次有多少种付款方法. Input 第一 ...
- 【BZOJ-1042】硬币购物 容斥原理 + 完全背包
1042: [HAOI2008]硬币购物 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1811 Solved: 1057[Submit][Stat ...
- bzoj1042: [HAOI2008]硬币购物
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #i ...
- 【BZOJ1042】【DP + 容斥】[HAOI2008]硬币购物
Description 硬币购物一共有4种硬币.面值分别为c1,c2,c3,c4.某人去商店买东西,去了tot次.每次带di枚ci硬币,买si的价值的东西.请问每次有多少种付款方法. Input 第一 ...
- BZOJ1042:[HAOI2008]硬币购物(DP,容斥)
Description 硬币购物一共有4种硬币.面值分别为c1,c2,c3,c4.某人去商店买东西,去了tot次.每次带di枚ci硬币,买si的价值的东西.请问每次有多少种付款方法. Input 第一 ...
随机推荐
- SQL TUNING——从近半小时到几十毫秒的一次优化
昨天,一个用户的现场人员打电话紧急求助,说他们的一个系统卡了,半天不出结果,严重的影响了他们的使用,我简单的问了几句:什么时候的事儿?答:就今天下午的事儿.问:数据库软硬件最近动过没?答:没动过.问: ...
- 微信小程序通过js动态修改css样式的方法(交流QQ群:604788754)
WXML <view class="page" style="background-color:{{pageBackgroundColor}}" > ...
- hadoop redis install (4)
reference: http://dblab.xmu.edu.cn/blog/131/ https://github.com/dmajkic/redis https://blog.csdn ...
- 51nod算法马拉松28-c
题解: 按照每一个要求,分类讨论,讨论压下去了多少 代码: #include<bits/stdc++.h> using namespace std; ,N=; int n,A,B,C,an ...
- prayer OJ M
这一题是一把辛酸泪啊...一个半小时ac的... 首先,考虑到如果要一条路径最小,那么肯定是没有值大于等于3的 显然如果有一个大于等于3的,那么这个数把路径分成两份,一份有k个,一个n-k-1个 那么 ...
- Swift网络封装库Moya中文手册之RxSwift
RxSwift Maya提供了一个可选的MoyaProvider 子类 - RxMoyaProvider.在网络请求完成时,我们不再使用 request() 函数的回调闭包,而是使用 Observab ...
- CUDA ---- CUDA库简介
CUDA Libraries简介 上图是CUDA 库的位置,本文简要介绍cuSPARSE.cuBLAS.cuFFT和cuRAND,之后会介绍OpenACC. cuSPARSE线性代数库,主要针对稀疏矩 ...
- 再谈Contacts中姓氏多音字排序错误问题
说到中国人的名字,那就不得不考虑多音字的问题,比如'单',在作为姓氏时应该读作'shan'而不是'dan'.但是在Contacts程序中却使用的是'D'来作为bucket label!这是为什么?如何 ...
- ARM裸板开发:07_IIC 通过IIC总线接口读写时钟芯片时间参数实现的总结
问题一:程序直接在iRAM内部可正常执行,而程序搬移(Nand ->SDRAM)之后,就不能正常运行了 #define NAND_SECTOR_SIZE 2048 /* 读函数 */ void ...
- 2.3 linux中的信号分析 阻塞、未达
信号的阻塞.未达: linux中进程1向进程2发送信号,要经过内核,内核会维护一个进程对某个信号的状态,如下图所示: 当进程1向进程2发送信号时,信号的传递过程在内核中是有状态的,内核首先要检查这个信 ...