洛谷综合题单 —— P1909 [NOIP2016 普及组] 买铅笔

[NOIP2016 普及组] 买铅笔

题目背景

NOIP2016 普及组 T1

题目描述

P 老师需要去商店买 $n$ 支铅笔作为小朋友们参加 NOIP 的礼物。她发现商店一共有 $3$ 种包装的铅笔,不同包装内的铅笔数量有可能不同,价格也有可能不同。为了公平起 见,P 老师决定只买同一种包装的铅笔。

商店不允许将铅笔的包装拆开,因此 P 老师可能需要购买超过 $n$ 支铅笔才够给小朋友们发礼物。

现在 P 老师想知道,在商店每种包装的数量都足够的情况下,要买够至少 $n$ 支铅笔最少需要花费多少钱。

输入格式

第一行包含一个正整数 $n$,表示需要的铅笔数量。

接下来三行,每行用 $2$ 个正整数描述一种包装的铅笔:其中第 $1$ 个整数表示这种包装内铅笔的数量,第 $2$ 个整数表示这种包装的价格。

保证所有的 $7$ 个数都是不超过 $10000$ 的正整数。

输出格式

$1$ 个整数,表示 P 老师最少需要花费的钱。

样例 #1

样例输入 #1

1
2
3
4
57
2 2
50 30
30 27

样例输出 #1

1
54

样例 #2

样例输入 #2

1
2
3
4
9998
128 233
128 2333
128 666

样例输出 #2

1
18407

样例 #3

样例输入 #3

1
2
3
4
9999
101 1111
1 9999
1111 9999

样例输出 #3

1
89991

提示

铅笔的三种包装分别是:

  • $2$ 支装,价格为 $2$;
  • $50$ 支装,价格为 $30$;
  • $30$ 支装,价格为 $27$。

P老师需要购买至少 $57$ 支铅笔。

如果她选择购买第一种包装,那么她需要购买 $29$ 份,共计 $2 \times 29 = 58$ 支,需要花费的钱为 $2 \times 29 = 58$。

实际上,P 老师会选择购买第三种包装,这样需要买 $2$ 份。虽然最后买到的铅笔数量更多了,为 $30 \times 2 = 60$ 支,但花费却减少为 $27 \times 2 = 54$,比第一种少。

对于第二种包装,虽然每支铅笔的价格是最低的,但要够发必须买 $2$ 份,实际的花费达到了 $30 \times 2 = 60$,因此 P 老师也不会选择。

所以最后输出的答案是 $54$。

【数据范围】

保证所有的 $7$ 个数都是不超过 $10000$ 的正整数。

【子任务】

子任务会给出部分测试数据的特点。如果你在解决题目中遇到了困难,可以尝试只解决一部分测试数据。

每个测试点的数据规模及特点如下表:

上表中“整倍数”的意义为:若为 $K$,表示对应数据所需要的铅笔数量 $n$ —定是每种包装铅笔数量的整倍数(这意味着一定可以不用多买铅笔)。

于 2022 年 12 月 23 日新加 Hack 数据三组。


这题乍一看是个背包问题,其实他只买一种包装的,因此问题其实就是比较哪种包装能以最少的钱满足最终对铅笔数量的要求。做法很简单,通过倍增快速度找到最优解。下面是代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include <iostream>

using namespace std;

int main() {
int ans;
int n;

cin >> n;

for (int i = 0; i < 3; i++) {
int price, count;

cin >> count >> price;

int total_price = price, total_count = count;
while (total_count < n) {
total_price <<= 1;
total_count <<= 1;
}

while (total_count > n) {
total_price -= price;
total_count -= count;
}

while (total_count < n) {
total_price += price;
total_count += count;
}

if (total_price < ans || ans == 0) {
ans = total_price;
}
}

cout << ans << endl;

return 0;
}