题意

输入一个 然后生成一个数列

要求 :

1,第一个数不超过

2,第个数和第个数的差值的绝对值不能超过1,且数列的长度无穷大

3,数列中所有的数之和为

求这个数列的最小值

因为要让数列尽可能地小 那么我们就让数列中的数尽可能地大

其中说到数列的长度为无穷大 那么他的意思是数列不能突然没了 也就是突然从一个大于1的数变没 可以理解成 最后的结尾一定是这样

这里我们去二分找答案 找数列中的最大值 要求左端小于 那么我们就可以理解成 有两种情况 最大值 就是最左边的 或者中间有一个凸起 最大值在中间

因此我们去二分找最大值就可以了

code

#include<bits/stdc++.h>
using namespace std;
typedef long long int ll; typedef unsigned long long ull; typedef long double ld;
const ll MOD = 1e9 + 7;
inline ll read() { ll s = 0, w = 1; char ch = getchar(); for (; !isdigit(ch); ch = getchar()) if (ch == '-') w = -1; for (; isdigit(ch); ch = getchar())    s = (s << 1) + (s << 3) + (ch ^ 48); return s * w; }

const int N = 1e5 + 7;
const int INF = 0x3f3f3f3f;
ll n , H , ans;

ll getsum(ll x){
    if(x % 2 == 0)
        return (x / 2 ) * (x + 1);
    else 
        return ((x + 1) / 2) * x;
}

bool check(ll x){
    ll sum1 = getsum(x) , sum2 , L;
    if(x <= H){
        if(sum1 > n)    return 0;
        L = n - sum1;
        if(L % x == 0)
            ans = min(ans , x + L / x);
        else
            ans = min(ans , x + L / x + 1);
        return 1;    
    }
    else{
        sum2 = getsum(x - 1) - getsum(H - 1);
        if(sum1 + sum2 > n)    return 0;
        L = n - sum1 - sum2;
        if(L % x == 0)
            ans = min(ans , x + x - H + L / x);
        else
            ans = min(ans , x + x - H + L / x + 1);
        return 1;    
    }
}

void solve(){
    n = read();
    H = read();
    ans = 1e18;
    ll l = 1 , r = (ll)sqrt(2.0 * n) + 10 , mid;
    while(l <= r){
        mid = (l + r) / 2;
        if(check(mid))
            l = mid + 1;
        else 
            r = mid - 1;
    }
    printf("%lld\n" ,  ans);
}

int main(void){
    solve();

    return 0;
}