传送门
分析见代码注释
#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;
}
ATM取款最优策略
本文介绍了一种解决ATM取款最优策略的问题,通过预处理不同面额纸币的最大可使用数量,来快速计算出获取指定金额所需的最少纸币数量。采用C++实现,并通过具体示例展示了算法的有效性和效率。
494

被折叠的 条评论
为什么被折叠?



