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 }
我就是我,颜色不一样的烟火 --- geloutingyu