cf873F(xjb+二分)

题目链接:http://codeforces.com/problemset/problem/837/F

 

题意:给出一个大小为 n 的数组 a 和一个数 k,每次操作后的到一个 a' 数组,a'i 为 a 数组中 ai 的前缀和.问最少需要几次操作能使得数组中最大的元素不小于 k.

 

思路:可以分类讨论一下,对于 n = 2 的情况直接可以计算出结果,对于 n = 3 的情况可以二分答案,对于 n >= 4 的情况直接暴力就好了.

 

代码:

 1 #include <iostream>
 2 #include <stdio.h>
 3 #define ll long long
 4 using namespace std;
 5 
 6 const int MAXN = 2e5 + 10;
 7 ll a[MAXN], k;
 8 
 9 bool is_ok(ll mid){ //注意可能会爆long long
10     double c = a[2] + mid * a[1] + (double)(1 + mid) * mid / 2 * (double)a[0];
11     return c >= k;
12 }
13 
14 ll get(void){
15     ll l = 1, r = 2e9;
16     while(l <= r){
17         ll mid = (l + r) >> 1;
18         if(is_ok(mid)) r = mid - 1;
19         else l = mid + 1;
20     }
21     return r + 1;
22 }
23 
24 int main(void){
25     ll x;
26     int n, indx = 0;
27     bool flag = false, ok = false;
28     scanf("%d%lld", &n, &k);
29     for(int i = 0; i < n; i++){
30         scanf("%lld", &x);
31         if(x) ok = true;
32         if(ok) a[indx++] = x; //注意前面的0对答案没有影响
33         if(x >= k){
34             flag = true;
35         }
36     }
37     if(flag){
38         puts("0");
39         return 0;
40     }
41     n = indx;
42     if(n == 2){
43         ll sol = (k - a[1] + a[0] - 1) / a[0];
44         printf("%lld\n", sol);
45     }else if(n == 3){
46         ll sol = get();
47         printf("%lld\n", sol);
48     }else{
49         ll sol = 0;
50         while(1){
51             sol++;
52             for(int i = 1; i < n; i++){
53                 a[i] += a[i - 1];
54                 if(a[i] >= k){
55                     printf("%lld", sol);
56                     return 0;
57                 }
58             }
59         }
60         cout << sol << endl;
61     }
62     return 0;
63 }
View Code

 

posted @ 2017-08-06 13:33  geloutingyu  阅读(567)  评论(0编辑  收藏  举报