题目: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. zk maxClientCnxns参数

    在zk模板配置文件中有: # the maximum number of client connections. # increase this if you need to handle more ...

  2. 小程序中的bindtap和catchtap的区别(交流QQ群:604788754)

    bindtap绑定的节点,如果他的父节点也有绑定事件,点击之后就会出现冒泡. catchtap绑定的节点,如果他的父节点也有绑定事件,点击之后不会出现冒泡.

  3. httpclient cookie相关介绍

    http状态管理 cookie是HTTP代理和目标服务器可以交流保持回话的状态信息的令牌或短包. httpclient使用Cookie接口来代表抽象的cookie令牌,在它的简单形式中http的coo ...

  4. bzoj1464

    题解: 简单bfs 显然不能到负数 也不能超过k两倍 代码: #include<bits/stdc++.h> using namespace std; ; int b[N],vis[N], ...

  5. Java——IO类,字节流缓冲区

    body, table{font-family: 微软雅黑} table{border-collapse: collapse; border: solid gray; border-width: 2p ...

  6. wilber3申请数据的直接目录寻找

    ftp://ds.iris.edu/pub/userdata/

  7. flash存储原理

    norflash 带有 SRAM接口,有足够的地址引脚来寻址,可以很容易地存取其内容每一字节:nandflash器件使用复杂的IO口串行的存取数据,读写操作采用512字节的块(也就是读/写某个字节,必 ...

  8. Hign-Speed Tracking with Kernelzied Correlation Filters

    reference:Hign-Speed Tracking with Kernelzied Correlation Filters questions: The core componet of mo ...

  9. [LeetCode&Python] Problem 876. Middle of the Linked List

    Given a non-empty, singly linked list with head node head, return a middle node of linked list. If t ...

  10. [LeetCode&Python] Problem 561. Array Partition I

    Given an array of 2n integers, your task is to group these integers into n pairs of integer, say (a1 ...