CodeForces 837F - Prefix Sums | Educational Codeforces Round 26

按tutorial打的我血崩,死活挂第四组- -

思路来自FXXL

/*
CodeForces 837F - Prefix Sums [ 二分,组合数 ]  |  Educational Codeforces Round 26
题意:
	设定数组 y = f(x) 使得 y[i] = sum(x[j]) (0 <= j < i)
	求初始数组 A0 经过多少次 f(x) 后 会有一个元素 大于 k
分析:
	考虑 A0 = {1, 0, 0, 0}
		A1 = {1, 1, 1, 1}  -> {C(0,0), C(1,0), C(2,0), C(3,0)}
		A2 = {1, 2, 3, 4}  -> {C(1,1), C(2,1), C(3,1), C(4,1)}
		A3 = {1, 3, 6,10}  -> {C(2,2), C(3,2), C(4,2), C(5,2)}
		A4 = {1, 4,10,20}  -> {C(3,3), C(4,3), C(5,3), C(6,3)}
	可知任意某个元素的贡献次数可以用组合数来表示,然后二分判定
	注意多个剪枝
*/
#include <bits/stdc++.h>
using namespace std;
#define LL long long
const int N = 200005;
LL k, n;
LL a[N];
bool check(LL t)
{
    double sum = 0, s;
    LL p, q;
    for (LL i = 0; i < n; i++)
    {
        if (a[i] == 0) continue;
        q = n-1-i + t-1;
        p = t-1;
        p = min(p, q-p);
        s = a[i];
        while(p)
        {
            s = s*q/p;
            p--, q--;
            if (s >= k) return 1;
        }
        sum += s;
        if (sum >= k) return 1;
    }
    return 0;
}
LL BinaryFind(LL l, LL r)
{
    LL mid;
    while (l <= r) {
        mid = (l+r)>>1;
        if (check(mid)) r = mid-1;
        else l = mid+1;
    }
    return l;
}
int main()
{
    scanf("%lld%lld", &n, &k);
    for (int i = 0; i < n; i++)
    {
        scanf("%lld", &a[i]);
        if (a[i] >= k) {
            puts("0"); return 0;
        }
    }
    printf("%lld\n", BinaryFind(1, k));
}

  

posted @ 2017-08-12 21:04  nicetomeetu  阅读(252)  评论(0编辑  收藏  举报