题目链接:CodeForces 760B Frodo and pillows
CodeForces 760B	Frodo and pillows(思维、二分、细节)
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;
}


相关文章: