解法一

首先不妨来思考一下怎样的一个付钱方案是最优的,假设需要支付 \(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. API 网关功能

    反向代理和路由 - 大多数项目采用网关的解决方案的最主要的原因.给出了访问后端 API 的所有客户端的单一入口,并隐藏内部服务部署的细节. 负载均衡 - 网关可以将单个传入的请求路由到多个后端目的地. ...

  2. 预训练模型时代:告别finetune, 拥抱adapter

    NLP论文解读 原创•作者 |FLIPPED 研究背景 随着计算算力的不断增加,以transformer为主要架构的预训练模型进入了百花齐放的时代.BERT.RoBERTa等模型的提出为NLP相关问题 ...

  3. JDK HttpClient 单次请求的生命周期

    HttpClient 单次请求的生命周期 目录 HttpClient 单次请求的生命周期 1. 简述 2. uml图 3. Http连接的建立.复用和降级 3.1 调用流程及连接的建立和复用 3.2 ...

  4. MySQL高级查询与编程笔记 • 【第3章 子查询】

    全部章节   >>>> 本章目录 3.1 子查询定义和单行子查询 3.1.1 子查询定义 3.1.2 单行子查询应用 3.1.4 实践练习 3.2 多行子查询应用 3.2.1 ...

  5. CSS3的nth-child() 选择器,表格奇偶行变色

    nth-child() 应用背景 CSS3的nth-child() 选择器,我之前很少用,在做表格偶数行变色的时候,我通常在绑定的时候,做一个js判断,来加一个css,从而使表格偶数行和奇数行颜色不一 ...

  6. 编写Java程序,使用Swing事件处理机制实现用户登录和英雄信息显示

    返回本章节 返回作业目录 需求说明: 使用Swing事件处理机制实现用户登录和英雄信息显示 实现思路: 创建LoginView类,该类用于显示登录界面,为登录按钮添加ActionListener事件, ...

  7. playwright--自动化(一):快速上手

    Playwright为现代 Web 应用程序提供可靠的端到端测试. 在JavaScript 和 TypeScript.Python..NET和Java 中都可以使用 Playwright 本人选择py ...

  8. Hadoop开启Kerberos安全模式

    Hadoop开启Kerberos安全模式, 基于已经安装好的Hadoop的2.7.1环境, 在此基础上开启Kerberos安全模式. 1.安装规划 已经安装好Hadoop的环境 10.43.159.7 ...

  9. C# 绘制印章

    最近有个.net core的项目要绘制印章功能,一个公司印章,一个个人印章,于是抽了点时间自己写了一个,现在分享出来 using System; using System.Collections.Ge ...

  10. CentOS7 常用命令汇总

    原文链接:https://blog.csdn.net/weixin_42208959/article/details/107970958 目录常用命令1.进程相关命令1.1 查询进程和结束进程1.2 ...