(File IO): input:loan.in output:loan.out
時間限制: 1000 ms 空間限制: 262144 KB 具體限制
Goto ProblemSet
題目描述
欠了 加侖牛奶。他必須在 天內將牛奶給 。但是,他不想將牛奶太早拿出手。另一方面,他不得不在還債上有所進展,所以他必須每天給 至少 加侖牛奶。
以下是 決定償還 的方式。首先他選擇一個正整數 。然後他每天都重複以下過程:
(1)假設 已經給了 加侖,計算 向下取整。令這個數爲 。
(2)如果 小於 ,令 等於 。
(3)給 加侖牛奶。
求 的最大值,使得 按照上述過程能夠在 天后給 至少 加侖牛奶 。
輸入
輸入僅有一行,包含三個空格分隔的正整數 和 ,滿足 。
注意這個問題涉及到的整數規模需要使用 位整數類型(例如,。
輸出
輸出最大的正整數 ,使得按照上述過程 會給 至少 加侖牛奶。
樣例輸入
10 3 3
樣例輸出
2
數據範圍限制
測試點 滿足 。
測試點 沒有額外限制。
提示
在這個測試用例中,當 時 第一天給 加侖,後兩天每天給 加侖。
解題思路
首先一定是二分,不必多說但是如果真的一天天掃過去,每次是的,明顯超時,所以在時會使用類似除法分塊的方法。假設現在剩下了的欠債,還剩t天
循環退出條件:,這時直接通過的成立與否判斷x的成立與否。。
那麼如果,那麼直接就以爲每天的還債量,於是。
否則就計算一下會有連續多少天的每日還債量是,假設這種情況持續天,那麼可以知道在天之後的還債量,而天之後的還債量。
代碼
#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<algorithm>
#include<iomanip>
#include<cmath>
using namespace std;
long long n,k,m,l,r,mid;
bool check(long long x)
{
long long kk=k,nn=n;
while(1)
{
long long y,yy;
y=nn/x;
if(y<m)
return m*kk>=nn;
yy=nn/y-x+1;
if(yy>kk)
yy=kk;
nn-=yy*y;
kk-=yy;
if(nn<=0)return 1;
if(kk==0)return 0;
}
}
int main(){
freopen("loan.in","r",stdin);
freopen("loan.out","w",stdout);
scanf("%lld%lld%lld",&n,&k,&m);
l=1,r=n;
while(l<r)
{
mid=(l+r+1)/2;
if(check(mid))
l=mid;
else
r=mid-1;
}
printf("%lld",l);
}