Byteasar 是一名餐厅厨师,他有 $n$ 个订单需要完成。每个订单都写在一张纸条上,所有纸条都串在一根签子上。Byteasar 的目标是尽可能快地完成所有订单。由于订单很多,为了提高效率,他只会从签子的顶部取订单。不过,他可以同时处理几道菜。具体来说,如果签子上还剩下 $k$ 张纸条,他可以:
- 取走最上面的一张纸条,并在 $jedno(k)$ 的时间内完成该订单。
- 如果 $k > 1$,他可以从顶部取走两张纸条,并在 $dwa(k)$ 的时间内完成这两份订单。
- 如果 $k > 1$,他可以从顶部取走 $\lfloor k/2 \rfloor$ 份订单,并在 $polowa(k)$ 的时间内完成它们。
这些操作会消耗 Byteasar 的体力,他初始的体力值为 $e$。具体而言,第三种操作非常费力,会使 Byteasar 的体力减少 1;第二种操作不消耗体力;而处理单个订单非常轻松,第一种操作会使 Byteasar 的体力增加 1。Byteasar 的体力值永远不能低于 0,除此之外,他会尽一切努力使完成所有订单的总时间最小化,即只要最终体力值非负,其具体数值并不重要。
请编写一个程序,确定完成所有订单所需的最短时间。你的程序需要与一个库进行交互,该库提供有关 Byteasar 及其厨房状态的所有必要信息。请注意本题的内存限制。
交互
要使用该库,请在程序开头包含以下内容:
- C/C++:
#include "ckuclib.h" - Pascal:
uses pkuclib;
该库提供以下函数和过程:
dajn,daje第一个函数返回一个整数 $n$,表示需要完成的订单数量;第二个函数返回一个整数 $e$,表示 Byteasar 的初始体力。- C/C++:
int dajn();int daje(); - Pascal:
function dajn: LongInt;function daje: LongInt;
- C/C++:
jedno(k),dwa(k),polowa(k)这些函数分别返回当签子上有 $k$ 张纸条时,执行处理一份、两份和一半(准确地说是 $\lfloor k/2 \rfloor$ 份)待处理订单所需的时间。对于 $k = 1$,dwa(k)和polowa(k)返回的值应被忽略。报告的时间是一个范围在 $1$ 到 $10^7$ 之间的整数。- C/C++:
int jedno(int k);int dwa(int k);int polowa(int k); - Pascal:
function jedno(k: LongInt): LongInt;function dwa(k: LongInt): LongInt;function polowa(k: LongInt): LongInt;
- C/C++:
odpowiedz(wynik)向库报告 $wynik$ 是完成所有订单所需的最短时间。调用此函数将终止你的程序执行。- C/C++:
void odpowiedz(int wynik); - Pascal:
procedure odpowiedz(wynik: LongInt);
- C/C++:
你的程序不能读取任何数据(既不能从标准输入,也不能从任何文件)。此外,它不能向文件或标准输出写入任何内容。它可以写入标准诊断输出 (stderr) —— 但请记住,这会消耗宝贵的时间。库可以多次查询相同的值。
子任务
测试集由以下子任务组成。在每个子任务中,可能包含多个测试组。
| 子任务 | 数据范围 | 分值 |
|---|---|---|
| 1 | $n, e \le 1000$ | 12 |
| 2 | $n, e \le 50\,000$ | 8 |
| 3 | $n, e \le 1\,000\,000$ | 80 |
样例
样例执行过程
| C/C++ | Pascal | Wynik |
|---|---|---|
n = dajn(); |
n := dajn; |
3 |
e = daje(); |
e := daje; |
1 |
p[3] = polowa(3); |
p[3] := polowa(3); |
1 |
p[2] = polowa(2); |
p[2] := polowa(2); |
4 |
j[2] = jedno(2); |
j[2] := jedno(2); |
2 |
j[1] = jedno(1); |
j[1] := jedno(1); |
5 |
d[2] = dwa(2); |
d[2] := dwa(2); |
6 |
odpowiedz(7); |
odpowiedz(7); |
— |
上述执行过程在形式上是正确的,但报告的结果可能不正确。从答案中可以推断出,执行 polowa 后接 dwa(成本为 $p[3] + d[2] = 7$)比执行一次 polowa 后接两次 jedno(成本为 $p[3] + j[2] + j[1] = 8$)更好。此外,当有三份待处理订单时,执行 jedno 是毫无意义的,因为 $p[3] = 1$ 而 $j[3] \ge 1$。由于 $e = 1$,无法执行两次 polowa。但如果不了解 dwa(3) 的成本,我们就无法判断执行 dwa 后接 jedno 是否比 7 更省时。
实现细节
在 dlazaw 文件夹中,有一个示例库可用于测试程序的正确性。该库从标准输入读取信息,格式如下:
- 第一行包含两个整数 $n$ 和 $e$;
- 第二行包含 $n$ 个范围在 $[1, 10^7]$ 之间的整数 —— 分别对应 $k = 1, \dots, n$ 时函数
jedno的值; - 第三行和第四行分别包含函数
dwa和polowa的值(格式相同);即使 $k=1$ 时的值会被忽略,也必须提供。
该库的输入样例在文件 kuc0.in 中提供。一旦执行了 odpowiedz 过程,库就会将报告的答案写入标准输出。
同一目录下包含使用该库的示例程序 kuc.c、kuc.cpp 和 kuc.pas。这些程序是不正确的;特别是,它们总是重复执行 polowa 操作,直到只剩下一张纸条,然后执行 jedno 操作。
要将你的程序与库一起编译,请执行以下命令:
- C:
gcc -O2 -static ckuclib.c kuc.c -lm -std=gnu99 - C++:
g++ -O2 -static ckuclib.c kuc.cpp -lm -std=c++11 - Pascal:
ppc386 -O2 -XS -Xt kuc.pas
你的程序文件和库文件应位于同一文件夹中。