题意:
给你一个序列,不断求前一个序列求前缀和数组,问你最早在第几个数组中出现大雨等于k的数字
解:
1、显然最后一个数字最大
2、我们求在第几次前缀和中,每一个位置上的数字对于最后一个位置上的贡献
3、找规律发现和组合数有关系
位置i在 第x次前缀和数组中,对最后一个答案的贡献是:
C(m,n) 其中m=n-i+1+(x-1)-1 ==n-i+x-1,n=x-1
我在给出一个我首先想到的一份TLE的思路:https://blog.csdn.net/qq_40675883/article/details/102214042
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const ll maxn =2e5+10;
ll rd() {ll t;scanf("%I64d",&t);return t;}
#define en '\n'
#define mem(a,b) memset(a,b,sizeof(a))
#define pb push_back
int n;
ll A[maxn],k,mx;
bool ok(ll x){
double s=0,tem=0;
for(int i=1;i<=n;i++){
if(!A[i])continue;
ll p=n-i+x-1;
ll q=x-1;
q=min(q,p-q);///C(p,q)
tem=A[i];
for(ll i=1;i<=q;i++){
tem=tem*(p-q+i)/i;
if(tem>=k)return 1;
}
s+=tem;
if(s>=k)return 1;
}
return 0;
}
signed main() {
#ifdef local
freopen("input2.txt","r",stdin);
#endif // local
n=rd(),k=rd();
for(int i=1;i<=n;i++){A[i]=rd();mx=max(mx,A[i]);}
if(mx>=k){puts("0");return 0;}
ll l=1,r=k;
while(l<=r){
ll mid=(l+r)>>1;
if(ok(mid)){
r=mid-1;
}else l=mid+1;
}cout<<l<<en;
}