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 }