解法一

首先不妨来思考一下怎样的一个付钱方案是最优的,假设需要支付 \(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. XSLT映射文件函数

    任何的编程语言或者是SQL语句都有内置的函数或方法,而强大灵活的xslt技术也是如此.熟练掌握XSLT的常用函数的用法,XSLT的应用将变得如此轻松,你会发现XSLT比想象中还要牛!以下是xslt数值 ...

  2. WiFi6模块 RW6852-PCIE

    RW6852-PCIE是一款高度集成的模块,支持2T2R 802.11ax解决方案,具有MU-MIMO.无线LAN (WLAN) PCI Express网络接口控制器和HS-UART混合接口.它结合了 ...

  3. .net core的配置介绍(一):IConfiguration

    说到配置,绝大部分系统都会有配置,不需要配置的系统是非常少的,想想以前做.net 开发时,我们常常将配置放到web.config中,然后使用ConfigurationManager去读取. 初次接触到 ...

  4. PHP 开启 Opcache 功能提升程序处理效率

    简介 Opcache 的前生是 Optimizer+ ,它是 Zend 开发的 PHP 优化加速组件.Optimizer+ 将 PHP 代码预编译生成的脚本文件 Opcode 缓存在共享内存中供以后反 ...

  5. Flink sql 之 两阶段聚合与 TwoStageOptimizedAggregateRule(源码分析)

    本文源码基于flink1.14 上一篇文章分析了<flink的minibatch微批处理>的源码 乘热打铁分析一下两阶段聚合的源码,因为使用两阶段要先开启minibatch,至于为什么后面 ...

  6. STM32F3 GPIO的八种模式及工作原理

    一.GPIO简介 GPIO(英语:General-purpose input/output),通用型之输入输出的简称,简单来说就是STM32可控制的引脚,STM32芯片的GPIO引脚与外部设备连接起来 ...

  7. html 基础 audio和video的基础使用

    基础标签 文本格式化标签: 标签 说明 <b></b>/<strong></strong> 加粗 <u></u>/<ins ...

  8. 使用.NET 6开发TodoList应用(22)——实现缓存

    系列导航及源代码 使用.NET 6开发TodoList应用文章索引 需求 有的时候为了减少客户端请求相同资源的逻辑重复执行,我们会考虑使用一些缓存的方式,在.NET 6中,我们可以借助框架提供的中间件 ...

  9. unittest_skip跳过用例执行(3)

    在执行测试用例时,有时候有些用例是不需要执行的,比如版本迭代用例弃用,测试周期短只需要执行优先级高的用例,那我们怎么办呢?难道删除这些用例?那下次执行时如果又需要执行这些用例时,又把它补回来?这样操作 ...

  10. unittest_TestSuite测试套件(2)

    在前面一章中演示了unittest如何执行一个简单的测试,但有两个问题: 我们知道测试用例的执行顺序是根据测试用例名称顺序执行的,在不改变用例名称的情况下,我们怎么来控制用例执行的顺序呢? 一个测试文 ...