Consider the function p(x), where x is an array of m integers, which returns an array y consisting of m + 1 integers such that yi is equal to the sum of first i elements of array x (0 ≤ i ≤ m).
You have an infinite sequence of arrays A0, A1, A2..., where A0 is given in the input, and for each i ≥ 1 Ai = p(Ai - 1). Also you have a positive integer k. You have to find minimum possible i such that Ai contains a number which is larger or equal than k.
Input
The first line contains two integers n and k (2 ≤ n ≤ 200000, 1 ≤ k ≤ 1018). n is the size of array A0.
The second line contains n integers A00, A01... A0n - 1 — the elements of A0 (0 ≤ A0i ≤ 109). At least two elements of A0 are positive.
OutputPrint the minimum i such that Ai contains a number which is larger or equal than k.
Examples2 2 1 1
1
3 6 1 1 1
2
3 1 1 0 1
0
转载来自包学长的博客 https://blog.csdn.net/howardemily/article/details/77389125
题目的意思是就是一个数组不断的前面相加 会多产生一个数在前面但是由于这个数字是0 所以说不用管它
然后呢....... 我没有想到二分心理卧槽了一下这都想不到
接下来就是 组合的数字
就像这个这样子 其实要求的是每个数字的对于最后一个数来说 的贡献次数
由找规律吧发现这是个排列组合
代码:
//MD我就没有想到二分 果然自己二分也是很薄弱这都想不到了
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n,k;
const int maxn=2*1e5+100;
ll a[maxn];
//可知任意某个元素的贡献次数可以用组合数来表示,然后二分判定
bool check(ll x)
{
double sum=0,tmp=0;
for(int i=0;i<n;i++)
{
if(a[i]==0)continue;
ll mm=x-1,nn=mm+n-1-i;//表示C下面的那个值
mm = min(nn - mm,mm); //优化啊 因为C(2,6)==C(4,6)//需要剪枝
tmp = a[i];
for(ll j=1;j<=mm;j++)
{
tmp=tmp*nn/j;
nn--;
if(tmp >= k)return true;
}
sum+=tmp;
if(sum>=k) return true;
}
if(sum>=k) return true;
return false;
}
// 对于k=3 C(2,7) C(2,6) C(2,5) C(2,4) C(2,3) C(2,)
ll sovle()
{
ll l=1,r=k,mid;/*这边是因为里面保证最少有一个是1所以说最多k次就可以达到了*/
while(l<=r)
{
mid=(l+r)/2;
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)
{
cout<<0<<endl;
return 0;
}
}//0次 所以直接输出 然后结束
printf("%lld\n",sovle());
return 0;
}