题意
输入一个和
然后生成一个数列
要求 :
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;
} 
京公网安备 11010502036488号