奇妙养乐多
时间限制: 1 Sec 内存限制: 128 MB
题目描述
小赵的第一次程序设计竞赛要开始了,比赛前当然要准备模板了,小赵开始整理自己的模板,小赵有
n
n
n 类模板,每类里面有
x
x
x 个知识点。
学知识当然要快乐啊,小赵决定每天每类模板只整理一个知识点,但是小赵如果在整理某类模板前喝一瓶他最爱的养乐多,他就会整理出这类模板最多
k
k
k 个知识点。养乐多可真好喝,所以小赵可以在整理之前喝很多瓶,喝
x
x
x 瓶养乐多的话,就可以整理最多
x
∗
k
x*k
x∗k 个知识点。
已知小赵一共有
m
m
m 瓶养乐多,他最少需要提前准备多少天才能在比赛前完成模板。(他可真懒呀)
输入
本题有多组测试数据。
每组测试数据第一行三个整数
n
,
m
,
k
n,m,k
n,m,k 如题面描述。
(
0
<
n
<
=
1
e
6
,
0
<
m
<
=
1
e
9
,
1
<
=
k
<
=
1000
)
(0<n<=1e6, 0<m<=1e9, 1<=k<=1000)
(0<n<=1e6,0<m<=1e9,1<=k<=1000)
第二行
n
n
n 个整数,第
i
i
i 个数字
x
i
x_i
xi 代表第
i
i
i 类模板的知识点的数量。
(
0
<
x
i
<
=
1
e
18
)
(0<x_i<=1e18)
(0<xi<=1e18)
输出
每组测试数据输出一行一个整数,代表提前准备的天数。
样例输入
5 2 2
1 2 3 4 5
样例输出
4
提示
第一天:0 1 2 3 3
第二天:0 0 1 2 1
第三天:0 0 0 1 0
第四天:0 0 0 0 0
思路
二分一下天数,在最后一天使用养乐多。
注意数据范围
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
const int maxn=1e6+5;
ll n,m,k;
ll w[maxn];
bool check(ll x) {
__int128 res = 0, t;
for (int i = 1; i <= n; ++i) {
if (w[i] >x) {
t = w[i] - x + 1;
if (t % k == 0) {
res += t / k;
} else {
res += t / k + 1;
}
}
if (res > m) return 0;
}
if (res > m) return 0;
return 1;
}
int main() {
//freopen("data.in","r",stdin);
while (~scanf("%lld %lld %lld", &n, &m, &k)) {
ll mx = 0;
for (int i = 1; i <= n; ++i) {
scanf("%lld", w + i);
mx = max(mx, w[i]);
}
__int128 l = 1, r = mx;
__int128 ans = 0;
while (l <= r) {
__int128 mid = (l + r) >> 1;
if (check(mid)) {
ans = mid;
r = mid - 1;
} else l = mid + 1;
}
printf("%lld\n", (ll)ans);
}
}