分饼干 题解(数学)

分饼干

在这里插入图片描述

解析

无需二分,使用纯粹的数学就可以以 O ( 1 ) O(1) O(1) 的时间复杂度解决。

先将 m m m 减去 n n n,也就是给每个人先发 1 1 1 颗糖果。

设班长拿了 x x x 块糖,左边有 l l l 个人,右边有 r r r 个人。贪心地考虑发糖情况,类似于一个金字塔一样,最好左右都构成公差为 1 1 1 的等差数列。以下分情况假设,分别列出方程进行求解,并验证答案是否符合假设。

  1. x > l and ⁡ x > r x>l \operatorname{and} x>r x>landx>r
    ( x − 1 + x − l ) l + ( x − 1 + x − r ) r 2 + x = m 2 x l − l 2 − l + 2 x r − r 2 − r + 2 x = 2 m 2 x l + 2 x r + 2 x = 2 m + l 2 + r 2 + l + r x ( 2 l + 2 r + 2 ) = 2 m + l 2 + r 2 + l + r x = 2 m + l 2 + r 2 + l + r 2 l + 2 r + 2 \frac{(x-1+x-l)l+(x-1+x-r)r}{2}+x=m\\ 2xl-l^2-l+2xr-r^2-r+2x=2m\\ 2xl+2xr+2x=2m+l^2+r^2+l+r\\ x(2l+2r+2)=2m+l^2+r^2+l+r\\ x=\frac{2m+l^2+r^2+l+r}{2l+2r+2} 2(x1+xl)l+(x1+xr)r+x=m2xll2l+2xrr2r+2x=2m2xl+2xr+2x=2m+l2+r2+l+rx(2l+2r+2)=2m+l2+r2+l+rx=2l+2r+22m+l2+r2+l+r

    特别注意等差数列的末项是 x − 1 x-1 x1,首项是 x − l x-l xl x − r x-r xr,项数是 l l l r r r。直接使用等差数列求和公式即可。

  2. x ≤ l and ⁡ x > r x\leq l \operatorname{and} x>r xlandx>r
    x ( x − 1 ) + ( x − 1 + x − r ) r 2 + x = m x 2 − x + 2 x r − r − r 2 + 2 x = 2 m 2 x r − r 2 + x 2 + x − r = 2 m x 2 + x ( 1 + 2 r ) − ( 2 m + r + r 2 ) = 0 \frac{x(x-1)+(x-1+x-r)r}{2}+x=m\\ x^2-x+2xr-r-r^2+2x=2m\\ 2xr-r^2+x^2+x-r=2m\\ x^2+x(1+2r)-(2m+r+r^2)=0 2x(x1)+(x1+xr)r+x=mx2x+2xrrr2+2x=2m2xrr2+x2+xr=2mx2+x(1+2r)(2m+r+r2)=0
    对于以上的方程,直接使用一元二次方程求根公式求解即可。注意:两个解只须保留较大的,因为只需计算非负解。

  3. x ≤ r and ⁡ x > l x\leq r \operatorname{and} x>l xrandx>l

    和情况 2 大同小异。

  4. x ≤ l and ⁡ x ≤ r x\leq l \operatorname{and} x\leq r xlandxr
    x ( x − 1 ) 2 × 2 + x = m x 2 − x + x = m x 2 = m x = m \frac{x(x-1)}{2}\times 2+x=m\\ x^2-x+x=m\\ x^2=m\\ x=\sqrt{m} 2x(x1)×2+x=mx2x+x=mx2=mx=m
    对于以上的每个可行解,将解向下取整后打擂台求最大值即可。最后不要忘了,每个人先发了 1 1 1 颗糖果, M a x Max Max 值要加 1 1 1

代码

// D
#include <bits/stdc++.h>
#define int long long
#define SIZE 200010
#define all(x) x.begin(), x.end()
#define debug(x) cout<<#x<<":"<<x<<endl;
using namespace std;

double solvex(int a, int b, int c)
{
	int x1=(-b+sqrt(b*b-4*a*c))*1.0/2*a;
	int x2=(-b-sqrt(b*b-4*a*c))*1.0/2*a;
	return max(x1, x2);
}

signed main()
{
	int n, m, k; cin>>n>>m>>k;
	m-=n;
	int s=0;
	int l=k-1;
	int r=n-l-1;
	int Max=0;
	// case 1: x>l && x>r
	double x=(int)(2*m+l*l+r*r+l+r)*1.0/(2*l+2*r+2);
	if(x>l && x>r)
		Max=max(Max, (int)x);
	// case 2: x<=l && x>r
	x=(int)solvex(1, 1+2*r, -(2*m+r+r*r));
	if(x>0 && x<=l && x>r)
		Max=max(Max, (int)x);
	// case 3: x>l && x<=r
	x=(int)solvex(1, 1+2*l, -(2*m+l+l*l));
	if(x>0 && x>l && x<=r)
		Max=max(Max, (int)x);
	// case 4: x<=l && x<=r
	x=(int)sqrt(m);
	if(x<=l && x<=r)
		Max=max(Max, (int)x);
	cout<<(int)(Max+1)<<endl;

	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值