题目
题目描述
某个国家的货币体系里有 种面值不同的纸币,从小到大面值分别是
当取款人去机取款 元的时候,机按一种贪心的策略给取款人发放钞票,策略如下:
首先,已发放钞票的集合是空集,每一次 机都会放一张当前可以放的最大面值的钞票进去,一直到集合里纸币面额等于 ,然后将集合里的纸币吐给取款人。
现在这个国家的公民觉得用钱把裤兜装的满满的会很有面子,但是他们又不想取出太多钱。现在他们问你:在最多取元的情况下,最多可以获得多少张纸币。
输入描述
第一行一个正整数,表示钞票的面值数
第二行个正整数,表示 种钞票的面值
第三行一个正整数,表示公民询问的数量
接下来行每行一个整数
输出描述
对于每个查询输出两个数字:取款的金额以及获得的纸币数量
若在不超过的情况下有多个金额取款获得的纸币数量都是最大值,输出任意一个金额即可
样例输入 复制 | 样例输出 复制 |
4 1 5 10 50 3 2 8 50 | 2 2 8 4 49 9 |
思路
f数组用来存前i个能达到的最大值,这个值必须得与a[i+1]有关,num数组存达到f[i]需要多少张,然后f是有序的,对于每一次询问进行二分查找,然后剩下的前看还能不能换多少a[i].
看看别人的思路
代码
#include<stack>
#include<cstdlib>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<queue>
#include<cstring>
#include<deque>
#include<vector>
#include<iostream>
#include<map>
#include<set>
#include<iomanip>
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define ll long long
using namespace std;
ll GCD(ll a,ll b){while(b^=a^=b^=a%=b);return a;}
const int inf=0x3f3f3f3f;
ll calc(ll x,ll y)
{
return x%y==0?(x/y-1):(x/y);
}
const int N = 2e5+7;
int n,m;
ll a[N],f[N],num[N],tt,t,res,x;
signed main()
{
#ifndef ONLINE_JUDGE
freopen("IO\\in.txt","r",stdin);
freopen("IO\\out.txt","w",stdout);
#endif
IOS
cin>>n;
for (int i=1;i<=n;i++) cin>>a[i];
//sort(a+1,a+1+n);
for (int i=1;i<n;i++)
{
t=max(calc(a[i+1]-f[i-1],a[i]),0ll);
f[i]=f[i-1]+t*a[i];
num[i]=num[i-1]+t;
}
f[n]=2e18;
//这里记得设置一个边界,不然下面的t会越界
cin>>m;
for (int i=1;i<=m;i++)
{
cin>>x;
t=upper_bound(f+1,f+1+n,x)-f;
res=x-f[t-1];
tt=res/a[t];
//看看剩下的还能不能换a[t],前面f[t-1]是固定的了
cout<<f[t-1]+tt*a[t]<<" "<<num[t-1]+tt<<endl;
}
return 0;
}