入门OJ:Coin
题目描述
你有n个硬币,第i硬币面值为ai,现在总队长想知道如果丢掉了某个硬币,剩下的硬币能组成多少种价值?(0价值不算)
输入格式
第一行一个整数n
第二行n个整数。,a1,a2…an。
1<=n<=100,1<=ai<=3000
输出格式
输出n行
第i行表示没有第i个硬币能组成多少种价值。
显然是个背包题,代价设计为硬币面值,价值设计为有几种方案组成当前面值。
那么设dp(i,j)表示前i个硬币有几种方案组成价值j,可以得出转移方程:
else:dp[i][j]=dp[i-1][j]
\]
压成一维之后:
\]
那么我们发现每一位的j可以由若干个状态更新过来。根据加法交换律,某个编号为i的硬币更新j状态的dp(j-val(i))先加后加都无所谓。根据这一点,我们可以认为任意一个硬币是最后被加进去的。
结合我们的结论和题目,当我们丢掉了一个硬币之后就相当于撤销这个硬币对dp数组的贡献。我们可以认为它是最后被更新上去的,所以我们只需要把更新的操作反着执行一遍即可:
for(register int j=val[i];j<=m;j++) dp[j]-=dp[j-val[i]];
然后我们的答案是能凑出的价值的个数,只需要枚举求一下有那些价值可以被≥1种方案凑出即可。
时间复杂度为O(NM)。
* dp数组在计算中会爆longlong,记得开高精。或者int128
* c数组可以直接用一个变量sum代替
#include<iostream>
#include<cstring>
#include<cstdio>
#define maxn 101
#define maxm 300001
using namespace std;
__int128 dp[maxm];
int n,m,val[maxn],c[maxm];
inline int read(){
register int x(0),f(1); register char c(getchar());
while(c<'0'||'9'<c){ if(c=='-') f=-1; c=getchar(); }
while('0'<=c&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
return x*f;
}
inline void update(){
for(register int i=1;i<=m;i++) c[i]=c[i-1]+(dp[i]>0);
}
inline void add(const int &val){
for(register int i=m;i>=val;i--) dp[i]+=dp[i-val];
}
inline void del(const int &val){
for(register int i=val;i<=m;i++) dp[i]-=dp[i-val];
}
int main(){
n=read(),dp[0]=1;
for(register int i=1;i<=n;i++) val[i]=read(),m+=val[i];
for(register int i=1;i<=n;i++) add(val[i]);
for(register int i=1;i<=n;i++){
del(val[i]),update(),printf("%d\n",c[m]),add(val[i]);
}
return 0;
}
入门OJ:Coin的更多相关文章
- 【入门OJ】2003: [Noip模拟题]寻找羔羊
这里可以复制样例: 样例输入: agnusbgnus 样例输出: 6 这里是链接:[入门OJ]2003: [Noip模拟题]寻找羔羊 这里是题解: 题目是求子串个数,且要求简单去重. 对于一个例子(a ...
- 【大视野入门OJ】1099:歌德巴赫猜想
Description 歌德巴赫猜想大家都很熟悉吧?给一个数,能够分解成两个素数的和.现在要给你一个n,6 <= n < 1000000,让你求他会分解成哪两个素数?如果存在多组解,则要求 ...
- 【大视野入门OJ】1083:数组的二分查找
Description 在1500个整数中查整数x的位置,这些数已经从小到大排序了.若存在则输出其位置,若不存在则输出-1. Input 第一行,一个整数x 后面1500行,每行一个整数 Output ...
- 入门oj 6492: 小B的询问
Description 小B有一个序列,包含N个1~K之间的整数.他一共有M个询问,每个询问给定一个区间[L..R],求Sigma(c(i)^2)的值,其中i的值从1到K,其中c(i)表示数字i在[L ...
- 入门oj 5499: 讲话模式
Description 每个人说话都有口头禅,现给出一个字符串,请求出其中出现次数最多的单词(不区分大小写). Input 输入一行,长度小于等于1048576的字符串输入至少包含一个字母或数字 Ou ...
- 入门oj 6451: The XOR Largest Pair之二
Description 今天小W用了1s不到的时候完成了这样一个题:在给定的N个整数 A_1,A_2,-,A_N中选出两个进行异或运算,得到的结果最大是多少?正当他志得意满时,L老师亮出了另一个题:给 ...
- 入门OJ:photo
题目描述 有N个人,来自K个家族.他们排成一行准备照相,但是由于天生的排外性,每个人都希望和本家族的人站在一起,中间不要加入别的家族的人.问最少从队列中去掉多少个就可以达到这个目的. 输入格式 第一行 ...
- 入门OJ:简单的网络游戏
题目描述 在某款极具技术含量的网络游戏中,佳佳靠着他的聪明智慧垄断了游戏中的油田系统.油田里有许多油井,这些油井排成一个M*N的矩形.每个油井都有一个固定的采油量.每两个相邻的油井之间有一条公路,这些 ...
- 入门OJ:最短路径树入门
题目描述 n个城市用m条双向公路连接,使得任意两个城市都能直接或间接地连通.其中城市编号为1..n,公路编号为1..m.任意个两个城市间的货物运输会选择最短路径,把这n*(n-1)条最短路径的和记为S ...
随机推荐
- 拒绝造轮子!如何移植并使用Linux内核的通用链表(附完整代码实现)
在实际的工作中,我们可能会经常使用链表结构来存储数据,特别是嵌入式开发,经常会使用linux内核最经典的双向链表 list_head.本篇文章详细介绍了Linux内核的通用链表是如何实现的,对于经常使 ...
- os模块和os.path模块常用方法
今天和大家分享python内置模块中的os模块和os.path模块. 1.什么是模块呢? 在计算机开发过程中,代码越写越多,也就越来越难以维护,所以为了可维护的代码,我们会把函数进行分组,放在不同的文 ...
- 如何查看打印机的IP地址和MAC地址
1. 打开控制面板,选择设备和打印机: 2. 选中打印机,右键单机,选择打印机 "属性": 3. 选择web服务,可以直接查看打印机的IP地址或MAC地址,如下图所示: 4. ...
- 将notepad++关联到右键菜单
Step1: 新建txt文本, 将以下内容复制到文本中: Windows Registry Editor Version 5.00 [HKEY_CLASSES_ROOT*\Shell\NotePad+ ...
- 记一次jedis并发使用问题JedisException: Could not return the resource to the pool
今天线上突然发现个奇怪的问题项目第一次启动的时候redis报错JedisException: Could not return the resource to the pool 直接访问接口的时候不报 ...
- 美团关于分布式ID实践方案细节
摘自https://tech.meituan.com/2019/03/07/open-source-project-leaf.html Leaf是美团基础研发平台推出的一个分布式ID生成服务,名字取自 ...
- 伯俊BOS2.0关于订金单的处理方案
订金单功能调整设计 一. 功能确认 BPOS关于订金的使用对应的是"预收单",原"预收单"设置有商品明细,根据客户对订金的需求,取消原有"商品 ...
- MyArray框架搭建与实现
#include<iostream> using namespace std; template<class T> class MyArray { public: //构造函数 ...
- Ubuntu 18.04 使用docker 部署gitlab并且使用自定义端口号
搭建原因 两个月前我搭建了公司的docker(无法自定义端口,),当初只想着把托管在GitHub的项目代码放在公司的服务器上面,后来忙着修改人脸服务器代码,忘记了,这个月由于领导提的需求比较多,还是托 ...
- github下载大文件太慢/失败
场景 github下载大文件,使用浏览器下载zip包到本地在下载到1G时失败, 使用 git clone ssh下载速度20k/s以下,已fq. 解决方法(亲测) 1.下载Github Desktop ...