很明显,可以通过二分xx的方式将极值问题转化为判定性问题。
暴力的方法是直接模拟每一天还的牛奶量,复杂度O(klogn)O(k\log n),能过四个点。
考虑优化二分的判定函数。我们将还的过程分为两部分。前一部分每次还的牛奶量都大于MM,后一部分则等于MM
容易发现,在前一部分的某些情况下,会有连续几天还同样的牛奶量。考虑从这个方向去优化复杂度。
rr为未还的奶量,这种情况下连续pp天还qq加仑。根据题意,q=rxq=\dfrac{r}{x}
推式子:

{r(p1)qx=qrpqx<q\begin{cases}\left\lfloor\dfrac{r-(p-1)\cdot q}{x}\right\rfloor=q\\\\\left\lfloor\dfrac{r-p\cdot q}{x}\right\rfloor<q\end{cases}

去掉下取整

{r(p1)qxqrpqx<q\begin{cases}\dfrac{r-(p-1)\cdot q}{x}\geq q\\\\\dfrac{r-p\cdot q}{x}<q\end{cases}

整理

{rpq+qqxrpq<qx\begin{cases}r-p\cdot q+q\geq q\cdot x\\\\r-p\cdot q<q\cdot x\end{cases}

{rqp+1xrqp<x\begin{cases}\dfrac{r}{q}-p+1\geq x\\\\\dfrac{r}{q}-p< x\end{cases}

rqx<prqx+1\dfrac{r}{q}-x<p\leq\dfrac{r}{q}-x+1

因为pp是一个整数,所以p=rqx+1p=\left\lfloor\dfrac{r}{q}-x+1\right\rfloor

这样的话,我们就可以一次性算出很多天的还奶量了。后半部分的计算非常简单,直接除一下即可。

复杂度O(nlogn)O(\sqrt n\log n)
代码(所有变量的定义与前文相同)

#include<iostream>
#define int long long
using namespace std;
int n,k,m;
bool judge(int x){
	int r=n,d=k;//d是剩余的天数
	while(1){
		int p,q;
		q=r/x;
		if(q<=m){
			return m*d>=r;//处理第二部分
		}
		p=r/q-x+1;
		if(p>d)p=d;//注意天数要在范围之内
		r-=p*q;
		d-=p;
		if(r<=0)return 1;
		if(d==0)return 0;
	} 
}
signed main(){
	cin>>n>>k>>m;
	int l=1,r=n,mid;
	while(l<r){
		mid=(l+r+1)>>1;//这里的二分边界要注意一下
		if(judge(mid))
			l=mid;
		else r=mid-1;
	}
	cout<<l;
	return 0;
}