解法一

首先不妨来思考一下怎样的一个付钱方案是最优的,假设需要支付 \(Y\) 元,第 \(a_i\) 种钱币支付了 \(s_i\) 张,那么必须有:\(s_i < \frac{a_{i + 1}}{a_i}\)。

否则一定可以通过调整减少钱币数量,那么若满足这个条件,付钱方案就是最优的了。

因为你付的钱和售货员找的钱当中一定存在一个 \(s_i = 0\),那么我们可以考虑将售货员找的钱取反就能恰好通过一个 \(s\) 序列表示一种可行的支付方案了。

于是问题转化为这样一个问题,求 \(s\) 序列的数量,满足:

\[\sum a_i \times s_i = X(-\frac{a_{i + 1}}{a_i} < s_i < \frac{a_{i + 1}}{a_i})
\]

同时通过这一条件,还可以推出 \(\forall i, \sum\limits_{j < i} a_j \times s_j < a_i\)。

因此,\(\forall i\) 应该要满足:\(|\sum\limits_{j \ge i} a_j \times s_j - X| < a_i\),注意到 \(a_i \mid \sum\limits_{j \ge i} a_j \times s_j\),因此这里的 \(\sum\limits_{j \ge i} a_j \times s_j\) 至多只有两种取值。

那么我们可以先计算出 \(\forall i, \sum\limits_{j \ge i} a_j \times s_j\) 的取值,然后就可以基于取值很少设计一个 \(dp\) 了。

不难发现可以令 \(f_{i, j}\) 表示 \(\sum\limits_{k \ge i} a_k \times s_k = j\) 时的方案数,转移时只需判断前后两个后缀之差这个位置是否能组成即可。

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define rep(i, l, r) for (int i = l; i <= r; ++i)
#define dep(i, l, r) for (int i = r; i >= l; --i)
const int N = 50 + 5;
int n, X, ans, a[N], cnt[N], b[N][3], dp[N][3];
signed main () {
cin >> n >> X;
rep(i, 1, n) {
cin >> a[i];
int L = ceil(1.0 * (X - a[i] + 1) / a[i]), R = (X + a[i] - 1) / a[i];
rep(j, L, R) b[i][++cnt[i]] = j * a[i];
}
rep(i, 1, cnt[n]) dp[n][i] = 1;
dep(i, 1, n - 1)
rep(j, 1, cnt[i])
rep(k, 1, cnt[i + 1])
if(abs(b[i + 1][k] - b[i][j]) / a[i] < a[i + 1] / a[i])
dp[i][j] += dp[i + 1][k];
rep(i, 1, cnt[1]) ans += dp[1][i];
cout << ans;
return 0;
}

解法二

同样需要解法一当中付钱方案最优的思考,接下来你会发现这个东西本质上是一个类似进制的东西。

假设 \(Y, Z\) 分别为你付的钱,收获员找的钱,那么应该满足 \(X + Z = Y\)

将这个东西类似于十进制加法一样在这个类进制下考虑,你会发现 \(Z, Y\) 中在某一位必须至少有一个为 \(0\)。

若 \(X\) 这位也为 \(0\) 那么 \(Z\) 这一位只能填 \(0\),否则 \(Z\) 只能填一个使得这一位恰好进位的数。

那么此时本质上之前位填的数对当前位的影响只有进位或不进位两种,所以可以令 \(f_{i, 0 / 1}\) 表示考虑到第 \(i\) 位之前有没有进位的方案数即可。

关于(类)进制的一条重要性质:\(\forall i, \sum\limits_{j < i} a_j \times s_j < a_i\)

另外这种涉及某种进制在一些位取值不同的情况下的运算时,一定要有类似于十进制数加法运算的思考。

ABC182 F Valid payments的更多相关文章

  1. AtCoder Beginner Contest 182 F

    F - Valid payments 简化题意:有\(n\)种面值的货币,保证\(a[1]=1,且a[i+1]是a[i]的倍数\). 有一个价格为\(x\)元的商品,付款\(y\)元,找零\(y-x\ ...

  2. Angular2 表单

    1. 说明 表单是Web程序中的重要组成部分,构建良好以及实用的表单必须解决如下几个问题: (1). 如何跟踪及更新表单的数据状态 (2). 如何进行表单验证 (3). 如何显示表单验证信息 Angu ...

  3. R12 付款过程请求-功能和技术信息 (文档 ID 1537521.1)

    In this Document   Abstract   History   Details   _afrLoop=2234450430619177&id=1537521.1&dis ...

  4. 迈向angularjs2系列(7):表单

    目录 一:校验表单的使用 1.搭建脚手架 2.校验表单的使用 3.select下拉列表的用法 一: 校验表单的使用 对于CRUD型的应用,表单是必备组件. 1.搭建脚手架 git clone http ...

  5. Gluon炼丹(Kaggle 120种狗分类,迁移学习加双模型融合)

    这是在kaggle上的一个练习比赛,使用的是ImageNet数据集的子集. 注意,mxnet版本要高于0.12.1b2017112. 下载数据集. train.zip test.zip labels ...

  6. 『MXNet』第九弹_分类器以及迁移学习DEMO

    解压文件命令: with zipfile.ZipFile('../data/kaggle_cifar10/' + fin, 'r') as zin: zin.extractall('../data/k ...

  7. 【转载】 pytorch之添加BN

    原文地址: https://blog.csdn.net/weixin_40123108/article/details/83509838 ------------------------------- ...

  8. Swift5 语言参考(六) 声明

    一个声明引入了一个新的名称或构建到你的程序.例如,您使用声明来引入函数和方法,引入变量和常量,以及定义枚举,结构,类和协议类型.您还可以使用声明来扩展现有命名类型的行为,并将符号导入到其他地方声明的程 ...

  9. 学习笔记之IKM C++ 11

    https://github.com/haotang923/interview/tree/master/IKM Q1. If most of the calls to function foo() b ...

随机推荐

  1. Codeforces 1113C: Sasha and a Bit of Relax(位运算|异或)

    time limit per test: 1 secondmemory limit per test: 256 megabytesinput: standard inputoutput: standa ...

  2. MCU变量加载过程

    前言 在开发mcu代码的时候经常会有些疑惑,变量是怎么在编译之后进入单片机的ram区的呢,特别是在使用keil开发的时候.后来在接触gcc编译器和自研的mcu后,终于明白了这个问题.实际上变量编译后被 ...

  3. matplotlib 进阶之origin and extent in imshow

    目录 显示的extent Explicit extent and axes limits matplotlib教程学习笔记 import numpy as np import matplotlib.p ...

  4. On the Optimization of Deep Networks: Implicit Acceleration by Overparameterization

    目录 引 主要内容 定理1 Claim 1 Claim 2 定理2 证明 定理1的证明 Claim 1 的证明 Kronecker product (克罗内克积) Theorem 2 的证明 代码 A ...

  5. vue为什么要设计成异步队列渲染

    异步队列渲染 上一篇文章是在vue2.0 中通过Object.defineProperty去拦截并监听数据变化的响应式原理,这篇文章将会沿着图谱继续深入探索,在依赖被通知变化了之后,会触发vue当中的 ...

  6. Storm集群使用DRPC功能Version1.0.1

    在Storm集群上开启DRPC功能, 基于Storm的1.0.1版本, 并且执行简单的例子测试. 1.DRPC概念 DRPC就是分布式远程过程调用. Storm里面引入DRPC主要是利用storm的实 ...

  7. 关于PaddleSharp GPU使用 常见问题记录

    在安装NVIDIA驱动过程中遇到一系列问题,记录如下! 附上PaddleSharp地址,大家喜欢可以关注 根据PaddleSharp官方说明需要安装驱动如下 CUDA 和 cuDNN 和 Tensor ...

  8. python3实现阿里云发短信

    一.准备工作 1.安装阿里云SDK pip install aliyun-python-sdk-core-v3 2.新建签名并等待审核通过 审核通过后,记下**[签名名称](参数1)**,程序中会用到 ...

  9. centos7安装使用vagrant

    https://blog.51cto.com/u_12173069/2312621 #download virtualbox https://www.virtualbox.org/wiki/Linux ...

  10. Texture+PBR两种工作流程

    一.导入Texture 1.Inpspector TextureSize 2的n次幂,底层图形学需要,计算更快:不使用2的倍数,系统也会添加像素补全2n: 有最大尺寸限制8k,cubemap最高4k: ...