小度有一些钞票资金, 一共有n种不同的面额, 对于面额为
小度想知道这部分资金最多能牛牛发放多少个月的工资?
包括n+1行,第一行包括两个正整数。
接下来的n行, 每行两个正整数, 即面额和该面额所拥有的钞票数量。
一个整数,表示最多能支付多少个月工资。
3 51 100 1 50 4 1 2
4
注意钱不能找零,所以:
100能支付一个月工资
50+1,50+1能支付两个月工资
50+50能支付一个月工资
即最多能支付四个月的工资。
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
class Money {
int value;
int nums;
public Money(int value, int nums) {
this.value = value;
this.nums = nums;
}
}
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int m = sc.nextInt();
List<Money> list = new ArrayList<>();
for (int i = 0; i < n; i++) {
int a = sc.nextInt();
int b = sc.nextInt();
list.add(new Money(a, b));
}
list.sort((a, b) -> b.value - a.value);
int ans = 0;
//先把大的直接发出去
for (Money money : list) {
if (money.value >= m) {
ans += money.nums;
money.nums = 0;
} else break;
}
//然后开始车轮战,每一趟while发出一个月工资
while (true) {
int needToPay = m;
//先从大面额开始涮一轮,在不超m的情况下,尽可能地拿大面额
for (Money money : list) {
if (money.nums == 0) continue;
int needNum = needToPay / money.value;
needNum = Math.min(needNum, money.nums);//最多取完,不能超了。
money.nums -= needNum;
needToPay -= needNum * money.value;
}
//刚好凑成了就结束这一趟
if (needToPay <= 0) {
ans++;
continue;
}
//再从小面额开始补(此时所有面额都已大于needToPay)
for (int i = list.size() - 1; i >= 0; i--) {
Money money = list.get(i);
if (money.nums == 0) continue;
money.nums--;
needToPay -= money.value;
ans++;
break;
}
if (needToPay > 0) break;
}
System.out.println(ans);
}
}
import java.util.*;
import java.io.*;
class Money{
public int value;//钞票面额
public int num;//该面额钞票的数量
}
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
public static void main(String[] args) throws IOException{
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
String[] s = in.readLine().split(" ");
int n = Integer.parseInt(s[0]), m = Integer.parseInt(s[1]);
Money[] a = new Money[n];
for(int i = 0; i < n; i++){
s = in.readLine().split(" ");
a[i] = new Money();
a[i].value = Integer.parseInt(s[0]);
a[i].num = Integer.parseInt(s[1]);
}
Arrays.sort(a, new Comparator<Money>(){//将钞票按从大到小排列
public int compare(Money a1, Money a2){
return a2.value - a1.value;
}
});
int large = 0;//用于后续直接从面额小于工资的钞票开始遍历
int month = 0;//能发工资的月份
//将面额大于等于工资的钞票全部取出直接发工资
while(large < n && a[large].value >= m){
month += a[large].num;
a[large].num = 0;
large++;
}
//处理面额小于工资的钞票
while(true){
int npay = m;//记录一个月还需要支付多少工资
//先从面额大的开始取,取到刚好不超过工资数量
for(int i = large; i < n; i++){
if(a[i].num == 0) continue;
int pNum = npay / a[i].value;//记录某个面额钞票能够补的数量
pNum = Math.min(pNum, a[i].num);//不能超过钞票剩余数量
npay -= pNum * a[i].value;
a[i].num -= pNum;
if(npay <= 0) break;//刚好取到工资的数量,直接跳出循环
}
//如果刚好取到了工资的数量,就直接发工资
if(npay <= 0){
month++;
continue;
}
//再从面额小的开始补工资
for(int i = n-1; i >= large; i--){
if(a[i].num == 0) continue;
while(npay > 0 && a[i].num > 0){
npay -= a[i].value;
a[i].num--;
}
if(npay <= 0){//工资补够了,跳出循环
month++;
break;
}
}
if(npay > 0) break;//钞票都补完了还没补够,没救了
}
System.out.println(month);
}
} import java.util.*;
class Money
{
public int mianZhi;
public int num;
}
public class Main
{
public static void main(String[] args)
{
Scanner in = new Scanner(System.in);
int numOfMoney = in.nextInt(); // 面值的种类
int salary = in.nextInt(); // 每月的工资
Money[] money = new Money[numOfMoney];
for (int i = 0; i < money.length; ++i)
{
money[i] = new Money();
money[i].mianZhi = in.nextInt();
money[i].num = in.nextInt();
}
Arrays.sort(money, new Comparator<Money>()
{
@Override
public int compare(Money m1, Money m2)
{
// 降序
return m2.mianZhi - m1.mianZhi;
}
}); // 对Money数组按照mianZhi降序排序
int month = 0;
// 因为不能找零,所以先把面值大于salary的钞票用完
int moreThanSalary = 0;
while (moreThanSalary < money.length && money[moreThanSalary].mianZhi >= salary) // 防止下标越界!!!
{
month += money[moreThanSalary].num;
money[moreThanSalary].num = 0;
++moreThanSalary;
}
// 然后用剩下的钞票开始组合(贪心),此时moreThanSalary就是面值小于salary的钞票的起始下标
while (true)
{
int remain = salary; // remain表示剩余的应发工资
for (int j = moreThanSalary; j < money.length; ++j) // 贪心一趟,结束后remain>=0
{
while (money[j].mianZhi <= remain && money[j].num > 0) // 当前面值小于remain,就使劲用
{
remain -= money[j].mianZhi;
--money[j].num;
}
}
for (int j = money.length - 1; j >= moreThanSalary && remain > 0; --j) // 若remain>0,从小面值到大面值再凑
{
if (money[j].num > 0)
{
remain -= money[j].mianZhi;
--money[j].num;
}
}
if (remain > 0) // remain仍然大于0,说明剩余的钞票已经不够用,结束循环
{
break;
}
else // 多发一个月的工资
{
++month;
}
}
System.out.println(month);
}
}
import java.util.*;
class Money {
int value;
int nums;
public Money(int value, int nums) {
this.value = value;
this.nums = nums;
}
}
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n ,m;
n = sc.nextInt();
m = sc.nextInt();
List<Money> list = new ArrayList<>();
for (int i = 0; i < n; i++) {
int value = sc.nextInt();
int nums = sc.nextInt();
Money money = new Money(value,nums);
list.add(money);
}
Collections.sort(list,(o1,o2) -> o2.value- o1.value);
int ans = 0;
// 第一种情况把大于工资的花完
for (int i = 0; i < list.size(); i++) {
//先把大钱用完
Money money = list.get(i);
if (money.value < m)
break;
ans += money.nums;
money.nums = 0;
}
while (true){
int res = m;
for (int i = 0; i < list.size(); i++) {
Money tmp = list.get(i);
if (tmp.nums == 0)
continue;
int need = res / tmp.value;
if (need > tmp.nums)
need = tmp.nums;
res = res - need * tmp.value;
tmp.nums -= need;
}
// 到这里所有可用的面额都大于 res ,从小开始补余额
for (int i = list.size() -1; i >= 0 && res>0; i--) {
Money tmp = list.get(i);
if (tmp.nums == 0)
continue;
int need = Math.max(res / tmp.value ,1 );
need = Math.min(need, tmp.nums);
tmp.nums = tmp.nums - need;
res -= need * tmp.value;
}
if (res >0)
break;
ans++;
}
// for (int i = 0; i < list.size(); i++) {
// System.out.println("value :"+list.get(i).value + " nums:"+list.get(i).nums);
// }
System.out.println(ans);
}
}
#include <bits/stdc++.h>
typedef std::pair<int, int> PAII;
using namespace std;
struct Money {
long long x;
int y;
bool operator<(Money m2) const {
return x < m2.x;
}
};
istream &operator>>(istream &is, Money &money) {
is >> money.x >> money.y;
return is;
}
int main() {
int n;
long long m;
cin >> n >> m;
long long totalSum = 0L;
vector<Money> moneyGroup(n);
unordered_map<int,int> modMoney;
for (int i = 0; i < n; ++i) {
cin >> moneyGroup[i];
totalSum += moneyGroup[i].x * moneyGroup[i].y;
}
if (totalSum < m) {
cout << 0 << endl;
} else {
sort(moneyGroup.begin(), moneyGroup.end());
long long ans = 0;
while (1) {
long long rest = m;
for (int i = n - 1; i >= 0 && rest > 0; --i) {
if (moneyGroup[i].y == 0)
continue;
// 有个整除关系感觉没用到。
// 先用大钱的思路没错,但是用小钱补的时候,小钱能提供更多的容错率
auto need = rest / moneyGroup[i].x;
if (need > moneyGroup[i].y) {
need = moneyGroup[i].y - 1;
}
rest -= need * moneyGroup[i].x;
moneyGroup[i].y -= need;
}
for (int i = 0; i < n && rest > 0; ++i) {
if (moneyGroup[i].y == 0)
continue;
auto need = max((int)(rest / moneyGroup[i].x),1);
if (need > moneyGroup[i].y) {
need = moneyGroup[i].y;
}
rest -= need * moneyGroup[i].x;
moneyGroup[i].y -= need;
}
if (rest > 0)
break;
++ans;
}
cout << ans;
}
}