题目链接:CodeForces 760B Frodo and pillows
首先要知道一点,要想主人公的枕头最多,那其他人的就要最少,也就是从主人公的两侧依次递减,即公差为1的等差数列。
思路:我们可以二分枚举枕头数,因为当主人公的枕头数定下来之后,就很好得到每一次的最优构造了(就是上面所说的一个简单的等差数列求和公式了。但是要分情况,在两边和不在两边,前者一个等差,后者两个等差),然后判断每一次的最优构造是否满足条件,进行二分。
注意:
1、long long防止数据溢出
2、CF上提交代码,要用%I64d,而不能用%llld
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<string>
#include<cstring>
using namespace std;
typedef long long ll;
const int maxn = 10010;
const int INF = 0x3f3f3f3f;
ll n,m,k;
bool judge(ll x)
{
if(k==1||k==n) //如果k在两边
{
ll res = 0;
if(x>n) res = ((x-n+1) + x) * n / 2;
else res = (1+x)*x/2;
return res <= m;
}
else //如果k不在两边,就分成了两部分
{
ll res1=0,res2=0;
if(x>k) res1 = ((x-k+1)+x)*k/2;
else res1 = (1+x)*x/2;
if(x>n-k+1) res2 = ((x-(n-k+1)+1)+x)*(n-k+1)/2;
else res2 = (1+x)*x/2;
return res1 + res2 - x <= m;
}
}
int main()
{
cin>>n>>m>>k; //n个人,m个枕头,在第k个位置
m = m-n;
if(m==0)
{
printf("1\n");
return 0;
}
ll ans = 0;
ll l = 0,r = m;
ll mid;
while(l<=r)
{
mid = (l+r)>>1;
if(judge(mid))
{
ans = mid;
l = mid+1;
}
else
r = mid-1;
}
printf("%I64d\n",ans+1);
return 0;
}