按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));
}