题意
输入一个和 然后生成一个数列
要求 :
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; }