E - Plants vs. Zombies

思路:直接二分答案,对每个答案进行check即可。check函数直接暴力写!(一开始想了半天以为是贪心,后来越想越麻烦,但这又不是可能是dp,所以直接暴力枚举答案即可)

#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<cstdio>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<stack>
//#define _for(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
typedef long long ll;
double eps=0.05;
ll mod=1e9+7;
const int INF=0x3f3f3f3f,inf =0x3f3f3f3f;
const int MAXN=2e3+10;
const int maxn = 1e7+10;
//ll inf=100000000000000;
//template<typename T>inline void read(T &x)
//{
//    x=0;
//    static int p;p=1;
//    static char c;c=getchar();
//    while(!isdigit(c)){if(c=='-')p=-1;c=getchar();}
//    while(isdigit(c)) {x=(x<<1)+(x<<3)+(c-48);c=getchar();}
//   x*=p;
//}
typedef unsigned long long ull;
const int N=2e5+7;
const double PI=acos(-1.0);
ll a[N];
ll m;
int n;
ll aa[N];
bool check(ll x){
    for(int i=0;i<n;i++){
        if(x%a[i]==0){
            aa[i]=x/a[i];
        }
        else {
            aa[i]=x/a[i]+1;
        }
    }
    ll ans=0;
    for(int i=0;i+1<n;i++){
        ans++;
        aa[i]--;
        if(aa[i]<=0){continue;}
        ans+=2*aa[i];
        aa[i+1]-=aa[i];
        if(ans>m)return false;
    }
    if(aa[n-1]>0){
        aa[n-1]--;ans++;
        ans+=aa[n-1]*2;
    }
    if(ans>m)return false;
    return true;

}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--){
        scanf("%d%lld",&n,&m);
        for(int i=0;i<n;i++){
            scanf("%lld",&a[i]);
        }
        ll l=0,r=1e12+10;
        ll aans=0;
        while(l<=r){
            ll mid=(l+r)/2;
            //cout<<mid<<endl;
            if(check(mid)){
                aans=mid;
                l=mid+1;
            }
            else {
                r=mid-1;
            }
        }
        printf("%lld\n",aans);
    }
    return 0;
}