FZYZOJ-1880 【UFO】水管

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 }

 

你可能感兴趣的:(ZOJ)