bzoj1042[HAOI2008]硬币购物
来源:互联网 发布:php内核源码分析 编辑:程序博客网 时间:2024/05/16 11:21
题意就不说了,原处就说的很明白。可以明显的看出是背包问题,但多重背包问题还是有一定难度的,容斥原理与背包的应用还是第一次见,一开始并没有想到(感谢hzw)。
解法是这样的:先求出不限制硬币多少的答案数,通过容斥定理,要减去第一种硬币超过数、第二种硬币超过数、第三种硬币超过数、第四种硬币超过数,加上第一、二种硬币同时超过数、加上第一、三种硬币同时超过数、加上第一、四种硬币同时超过数、加上第二、三种硬币同时超过数、加上第二、四种硬币同时超过数、加上第三、四种硬币同时超过数………………由此类推,就将超过的都减掉了,剩下的就是答案!
恶心但好理解的for
#include<cstdio>#include<cstring>using namespace std;typedef long long LL;LL c[5],d[5],f[110000];int main(){ for(int i=1;i<=4;i++)scanf("%d",&c[i]); memset(f,0,sizeof(f));f[0]=1; for(int i=1;i<=4;i++) for(int j=c[i];j<=100000;j++) f[j]+=f[j-c[i]]; int n,s; scanf("%d",&n); while(n--) { for(int i=1;i<=4;i++)scanf("%d",&d[i]); scanf("%d",&s);LL ans=f[s]; for(int i=1;i<=4;i++) if(s>=(d[i]+1)*c[i])ans-=f[s-(d[i]+1)*c[i]]; for(int i=1;i<=3;i++) for(int j=i+1;j<=4;j++) if(s>=((d[i]+1)*c[i]+(d[j]+1)*c[j])) ans+=f[s-((d[i]+1)*c[i]+(d[j]+1)*c[j])]; for(int i=1;i<=2;i++) for(int j=i+1;j<=3;j++) for(int k=j+1;k<=4;k++) if(s>=((d[i]+1)*c[i]+(d[j]+1)*c[j]+(d[k]+1)*c[k])) ans-=f[s-((d[i]+1)*c[i]+(d[j]+1)*c[j]+(d[k]+1)*c[k])]; if(s>=((d[1]+1)*c[1]+(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])]; printf("%lld\n",ans); } return 0;}
好看的dfs
#include<cstdio>#include<cstring>using namespace std;typedef long long LL;LL c[5],d[5],f[110000],ans;void dfs(int x,int k,int sum){ if(sum<0)return ; if(x==5) { if(k%2==1)ans-=f[sum]; else ans+=f[sum]; return; } dfs(x+1,k+1,sum-(d[x]+1)*c[x]); dfs(x+1,k,sum);}int main(){ for(int i=1;i<=4;i++)scanf("%d",&c[i]); memset(f,0,sizeof(f));f[0]=1; for(int i=1;i<=4;i++) for(int j=c[i];j<=100000;j++) f[j]+=f[j-c[i]]; int n,s; scanf("%d",&n); while(n--) { for(int i=1;i<=4;i++)scanf("%d",&d[i]); scanf("%d",&s); ans=0;dfs(1,0,s); printf("%lld\n",ans); } return 0;}
By_yzh
2 4
- BZOJ1042: [HAOI2008]硬币购物
- BZOJ1042: [HAOI2008]硬币购物
- bzoj1042: [HAOI2008]硬币购物
- BZOJ1042: [HAOI2008]硬币购物
- [BZOJ1042] [HAOI2008]硬币购物
- bzoj1042【HAOI2008】硬币购物
- [bzoj1042][HAOI2008]硬币购物
- bzoj1042[HAOI2008]硬币购物
- 【bzoj1042】[HAOI2008]硬币购物
- [bzoj1042][HAOI2008]硬币购物
- bzoj1042: [HAOI2008]硬币购物
- BZOJ1042: [HAOI2008]硬币购物
- bzoj1042 [HAOI2008]硬币购物
- bzoj1042[HAOI2008] 硬币购物
- 【bzoj1042】[HAOI2008]硬币购物
- bzoj1042 [HAOI2008]硬币购物
- 【bzoj1042】[HAOI2008]硬币购物
- bzoj1042: [HAOI2008]硬币购物
- Windows平台下一些好玩的技巧
- Swift学习之六:元组(Tuples)
- transient
- DAPM 概述(中文翻译)/ dapm.txt
- 如何开启ubuntu共享桌面
- bzoj1042[HAOI2008]硬币购物
- 关于webview需要知道的东西
- nyoj 133 子序列(尺取法+离散化)
- Java与JS互掉示例2
- HNNU 11656 错误的算法【 湖南省第十一届大学生计算机程序设计竞赛,模拟】
- BZOJ2280: [Poi2011]Plot
- C++ 复合类型(三)--数组vector、array
- 单选框(复选框)按钮样式
- Combination Sum