在這里解釋一下二分內judge()的操作方式
首先一定是二分\(x\),不必多說
但是如果真的一天天掃過去,每次judge()是\(O(k)\)的,明顯超時
所以在judge()時會使用類似除法分塊的方法
假設現在剩下了\(r\)的欠債,還剩\(t\)天
循環退出條件:\(r\leqslant0||t==0\),這時直接通過\(r\leqslant0\)的成立與否判斷\(x\)的成立與否
那么\(y=\lfloor\frac{r}{x}\rfloor\)
如果\(y\leqslant m\),那么直接就以\(m\)為每天的還債量,於是\(r-=tm,t=0\)
否則就計算一下會有連續多少天的每日還債量是\(y\),假設這種情況持續\(a\)天,那么可以知道在\(a-1\)天之后的還債量\(=y\),而\(a\)天之后的還債量\(<y\)
於是有方程\(\lfloor\frac{r-(a-1)y}{x}\rfloor=y,\lfloor\frac{r-ay}{x}\rfloor<y\)
改為不等式:\(\frac{r-(a-1)y}{x}\geqslant y,\frac{r-ay}{x}<y\)
變形:\(a\leqslant\frac r y-x+1,a>\frac r y-x\)
因為\(a\)是正整數,所以\(a=\lfloor\frac r y-x+1\rfloor\)
於是在之后的連續\(a\)天,花費都是\(y\)
那么就可以快速把答案“跳”出來了
Time complexity: \(O(n^\frac{1}{2}\log n)\)(后面有證明)
Memory complexity: \(O(1)\)
細節請見代碼(代碼中用\(rm\)代替\(r\))
//This program is written by Brian Peng.
#pragma GCC optimize("Ofast","inline","no-stack-protector")
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define Rd(a) (a=read())
#define Gc(a) (a=getchar())
#define Pc(a) putchar(a)
int read(){
register int x;register char c(getchar());register bool k;
while(!isdigit(c)&&c^'-')if(Gc(c)==EOF)exit(0);
if(c^'-')k=1,x=c&15;else k=x=0;
while(isdigit(Gc(c)))x=(x<<1)+(x<<3)+(c&15);
return k?x:-x;
}
void wr(register int a){
if(a<0)Pc('-'),a=-a;
if(a<=9)Pc(a|'0');
else wr(a/10),Pc((a%10)|'0');
}
signed const INF(0x3f3f3f3f),NINF(0xc3c3c3c3);
long long const LINF(0x3f3f3f3f3f3f3f3fLL),LNINF(0xc3c3c3c3c3c3c3c3LL);
#define Ps Pc(' ')
#define Pe Pc('\n')
#define Frn0(i,a,b) for(register int i(a);i<(b);++i)
#define Frn1(i,a,b) for(register int i(a);i<=(b);++i)
#define Frn_(i,a,b) for(register int i(a);i>=(b);--i)
#define Mst(a,b) memset(a,b,sizeof(a))
#define File(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout)
int n,k,m,l(1),r,md;
bool jdg(int x);
signed main(){
r=Rd(n),Rd(k),Rd(m);
while(l<=r)jdg(md=(l+r)>>1)?l=md+1:r=md-1;
wr(l-1),exit(0);
}
bool jdg(int x){
int y,a,rm(n),t(k);
while(t&&rm>0){
y=rm/x;
if(y>m)a=min(rm/y-x+1,t),rm-=a*y,t-=a;
else rm-=t*m,t=0;
}
return rm<=0;
}
現在是復雜度證明
每次judge()的時間消耗就是不同\(y\)值的數量,假設是\(d\)
那么最壞情況就是不同的\(y\)值分別是\(1,2,\cdots,d\),而且每個只出現一次
那么就有\(\sum_{i=1}^d i\geqslant n\),此時使\(d\)最小
利用等差數列求和公式:\(\frac{d(d+1)}{2}\geqslant n\)
當\(d=\lceil (2n)^\frac{1}{2}\rceil\)時就滿足不等式
所以\(d=O(n^\frac{1}{2})\)
於是最終時間復雜度\(O(d\log n)=O(n^\frac{1}{2}\log n)\),可以AC
