- 题目链接:CF985D
- 标签:二分、思维
- 题目大意:对于给定的n、H,将n分成a1、a2、…、an,其中ai始终不大于H,且相邻两项之差不大于1,(且最后一项也必须为1)求最少分成几个数
- 思路:
-
此题的核心点在于确定最高峰的高度,有两种情况:
1.等差数列1~H之和小于n,则总点的树目为H + [ ( n - S ) / H ] + 1
2.等差数列1~H之和大于n,则找出1-k,使得和数不大于n的最大值,后续操作重复1. -
不得不提一下等差数列公式:S= ( 1 + K ) * K / 2 = ( K + K2 ) / 2
-
求 n - S > = 0 时,K的最大值, 可以利用二分法
-
- 代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll n,h;
bool check(ll mid){//防止爆ll
if((double)(mid+1)>=2.0*n/mid)
return true;
return false;
}
bool check2(ll mid){
ll tmp=(mid-h+1)/2;
ll sum=(h+h+tmp-1)*tmp+(h-1)*h/2;
if((mid-h+1)%2)
sum+=(h+tmp);
if(sum>=n)return true;
return false;
}
int main(){
cin>>n>>h;
ll ans,mid;
if(check(h)){
ll l=1,r=h;
while(l<=r){
mid=(l+r)/2;
if(check(mid))
ans=mid,r=mid-1;
else l=mid+1;
}
}
else {
ll l=h,r=2e9;
while(l<=r){
mid=(l+r)/2;
if(check2(mid))
ans=mid,r=mid-1;
else l=mid+1;
}
}
cout<<ans;
}