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)); }
我自倾杯,君且随意