P1880 -- 【ufo】水管

时间限制:1000MS      内存限制:131072KB      通过/提交人数:32/100

状态:      标签:    数学问题-组合数学   无   无

Description

lzl:我最近买了一套面积2147483647的房子,可是黄地产开发商sxbk,竟然只给我装了一根水管。

ufo:还不够么?

lzl:鉴于我的增肥计划,我需要n个厨房,每个厨房至少得有1根水管接入吧。

ufo:。。。不要急,你看我给你送来了神奇的水管转换器,可以使水管1变x。

ufo拥有1变2至1变k的转换器各一个,问至少要几个转换器才能满足lzl的增肥需求。

下图是1变4的转换器示意图

器

Input Format

两个整数n,k

Output Format

满足lzl需求需要用到转换器最少个数,不能满足的输出-1

Sample Input

4 3

Sample Output

2

Hint

对于30%的数据1 ≤ n ≤ 10, 2 ≤ k ≤ 10

对于100%的数据1 ≤ n ≤ 10^18, 2 ≤ k ≤ 10^9

ufo:黄地产给你装下水管没?

lzl:没。。没事,大肚能容天下事   嗝~~~

 

题解

      根据贪心的思想,必须从大到小选用转换器才能得到最优解。不难发现,在这个选用的过程中,每次增加的水管数量构成等差数列,那么可以运用等差数列求和公式。

      方法一:在[1,k]中二分答案,用等差数列求和公式判定得到最优解。

      方法二:由等差数列求和公式得到一元二次方程,解方程。

 

代码

 

 1 #include <cstdio>
 2 #include <iostream>
 3 using namespace std;
 4 
 5 long long N, K;
 6 long long L, R;
 7 
 8 double Calc(long long K, long long N) {
 9     N = N - 1;
10     return (double) (K - 0.5) * N - 0.5 * N * N + 1;
11 }
12 
13 int main() {
14     scanf("%lld%lld", &N, &K);
15     if (Calc(K, K) < N) {
16         printf("-1\n");
17         return 0;
18     }
19     L = 1;
20     R = K;
21     while (L <= R) {
22         long long Mid = (L + R) >> 1;
23         double Sum = Calc(K, Mid);
24         if (Sum < N) L = Mid + 1;
25         else R = Mid - 1;
26     }
27     printf("%lld\n", L - 1);
28 }