洛谷题目传送门

我实在是太弱了,第一次正儿八经写背包DP,第一次领会如此巧妙的容斥原理的应用。。。。。。

对每次询问都做一遍多重背包,显然T飞,就不考虑了

关键就在于每次询问如何利用重复的信息

我这么弱,当然是想不到容斥原理的啦

暂且先当成完全背包,每种硬币可使用无限次,预处理\(f\)数组,\(f[i]\)等于买价值\(i\)的东西的总方案数

然后就要从中减去不合法的。首先肯定会有一种硬币超额使用,第\(j\)中硬币等于说强制选了\(d_j+1\)个,剩下的依然随便选,那么第

\(j\)种硬币超额的不合法的方案数等于\(f[s-(d_j+1)*c_j]\),于是从答案里减去\(\sum_{j=1}^4f[s-(d_j+1)*c_j]\)

还要注意,第一种第二种都超额、第一种第三种都超额、第一种第四种都超额、第二种第三种都超额、第二种第四种都超额、第三种第四种都超额的方案在上一步中都被减了两次,所以额外都加一次回来。。。。。。(接着把容斥做下去就不说了)

复杂度降到\(O(4maxs+4×2^4tot)\),轻松通过

注意开longlong就好啦

#include<cstdio>
#define R register
typedef long long LL;
const int S=100009;
LL f[S]={1ll};
int main(){
R int c[4],d[4],tot,i,j,k,now,s,ss,tmp;
R LL ans;
for(j=0;j<4;++j)scanf("%d",&c[j]);
scanf("%d",&tot);
for(j=0;j<4;++j)
for(i=c[j];i<S;++i)
f[i]+=f[i-c[j]];//完全背包预处理
while(tot--){
for(j=0;j<4;++j)scanf("%d",&d[j]);
scanf("%d",&s);
ans=f[s];
for(ss=1;ss<=15;++ss){//二进制数枚举集合,容斥
now=s;
for(tmp=ss,j=k=0;tmp;tmp>>=1,++j)
if(tmp&1)k^=1,now-=(d[j]+1)*c[j];
//注意k的作用,判断奇偶
if(now>=0)k?ans-=f[now]:ans+=f[now];
}
printf("%lld\n",ans);
}
return 0;
}

最新文章

  1. CSS系列:CSS中盒子模型
  2. Unity3D的四种坐标系
  3. SQL 递归树 子父节点相互查询
  4. C++二维码相关库编译
  5. chroot详解
  6. [Java] 过滤文件夹
  7. GotFocus和PreviewLeftButtonDown事件
  8. B - Numbers That Count
  9. Ubuntu14.04安装Mongodb
  10. 关于C#文件复制(递归)
  11. 关于金额,重量等浮点数的数据库字段设计(用Int,Long代替浮点数计算)
  12. hadoop 基本命令
  13. Ansible(一) 配置安装
  14. FineUIPro/Mvc/Core v5.4.0即将发布(Core基础版,新功能列表)!
  15. Nowcoder contest 370B Rinne Loves Graph 【分层图最短路】
  16. java枚举类型
  17. 顺序队列(C语言)
  18. MDX 脚本语句 -- Scope
  19. 获取天气预报API5_统计最容易生病时间段
  20. gtk_init()

热门文章

  1. 利用WebHook实现PHP自动部署Git代码
  2. 树形DP 复习
  3. ISCSI target的两种安装方法
  4. 20155310 Exp9 Web安全基础实践
  5. 2017-2018-2 《网络对抗技术》20155322 Exp9 web安全基础
  6. Oracle中,如何查看FRA(Flashback Recovery Area)的利用率
  7. libgdx学习记录11——平铺地图TiledMap
  8. Linux每天一个命令:tar
  9. 【ORACLE】数据库空闲1分钟自动断开
  10. Dive查看docker镜像层信息