牛客练习赛86 C. 取钱(DP)

本文介绍了一种解决ATM取款最优策略的问题,通过预处理不同面额纸币的最大可使用数量,来快速计算出获取指定金额所需的最少纸币数量。采用C++实现,并通过具体示例展示了算法的有效性和效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

传送门
分析见代码注释

#include <bits/stdc++.h>

using namespace std;
//-----pre_def----
const double PI = acos(-1.0);
const int INF = 0x3f3f3f3f;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
#define IOS ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
#define fir(i, a, b) for (int i = (a); i <= (b); i++)
#define rif(i, a, b) for (int i = (a); i >= (b); i--)
#define endl '\n'
#define init_h memset(h, -1, sizeof h), idx = 0;
#define lowbit(x) x &(-x)

//---------------
const int N = 2e5 + 10;
int n, m, d[N];
LL a[N], sum[N], cnt[N];
void init() {}
int main()
{
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
    int StartTime = clock();
#endif
    scanf("%d", &n);
    fir(i, 1, n) scanf("%lld", &a[i]);
    /*
    如果要取的面额大于等于a[i]-->atm直接吐出一张a[i]的纸币
    预处理出不超过当前钞票面额的最多钞票数
    */
    a[n + 1] = 1e18;
    fir(i, 1, n)
    {
        //在总额不超过a[i+1]的前提下,第i张纸币最多取t张,此时保证了纸币数量最大且总额不超(如果大于等于a[i+1]了,那么只需要一张a[i+1]就行了)
        // sum[i-1]+t*a[i] < a[i+1]
        LL t = (a[i + 1] - sum[i - 1] - 1) / a[i];
        cnt[i] = cnt[i - 1] + t;
        sum[i] = sum[i - 1] + t * a[i];
    }
    scanf("%d", &m);
    fir(i, 1, m)
    {
        LL x;
        scanf("%lld", &x);
        int tmp = lower_bound(sum + 1, sum + 1 + n, x) - sum;
        LL res = cnt[tmp - 1] + (x - sum[tmp - 1]) / a[tmp];
        //(x - sum[tmp - 1]) / a[tmp] 表示:还能取多少的第tmp大面值的纸币
        printf("%lld %lld\n", sum[tmp - 1] + (x - sum[tmp - 1]) / a[tmp] * a[tmp], res);
    }
#ifndef ONLINE_JUDGE
    printf("Run_Time = %d ms\n", clock() - StartTime);
#endif
    return 0;
}
### 关于练习赛14 B题的解析 目前未找到直接针对练习赛14 B题的具体题解或比赛经验。然而,可以通过分析类似的题目以及常见的算法竞赛技巧来推测可能的解决方案。 #### 类似问题的解决思路 在算法竞赛中,B类题目通常涉及基础数据结构的应用或者简单的数学推导。以下是几种常见类型的处理方式: 1. **字符串操作** 若该题涉及到字符串处理,则可以利用C++中的`std::string`库函数[^2],例如查找子串、替换字符等操作。 2. **数组与序列** 对于数组或序列的操作,动态规划(Dynamic Programming, DP)是一种常用方法。通过定义状态转移方程,逐步解决问题。例如,在某些情况下,可以用滚动数组优化空间复杂度[^3]。 3. **图论模型** 如果题目描述中有提到节点之间的关系,可能是图论问题。此时可采用广度优先搜索(BFS)、深度优先搜索(DFS),甚至最短路径算法如Dijkstra或Floyd-Warshall来建模并求解[^1]。 4. **模拟与暴力枚举** 当面对简单逻辑判断或多步运算时,“模拟”成为一种有效手段。即按照题目给定规则一步步实现程序流程,虽然时间效率未必最优,但对于小规模输入非常适用[^5]。 下面提供一段伪代码框架供参考: ```cpp #include <iostream> using namespace std; int main(){ int testCase; cin >> testCase; while(testCase--){ // 输入处理... // 解决方案核心部分 // 输出结果 } } ``` #### 提升竞赛表现的经验分享 为了更好地准备此类赛事,建议采取以下策略: - 定期参与线上平台举办的各类比赛积累实战经历; - 复盘每次赛后官方发布的详解文档学习新知; - 加强基础知识巩固的同时拓宽思维边界尝试不同领域挑战项目; ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值