The universe said you |

Momo·Trace

园龄:3年3个月粉丝:6关注:1

银行贷款

银行贷款

题目描述

当一个人从银行贷款后,在一段时间内他(她)将不得不每月偿还固定的分期付款。这个问题要求计算出贷款者向银行支付的利率。假设利率按月累计。

输入格式

三个用空格隔开的正整数。

第一个整数表示贷款的原值 w0,第二个整数表示每月支付的分期付款金额 w,第三个整数表示分期付款还清贷款所需的总月数 m

输出格式

一个实数,表示该贷款的月利率(用百分数表示),四舍五入精确到 0.1%

样例 #1

样例输入 #1

1000 100 12

样例输出 #1

2.9

提示

数据保证,1w0,w23111m3000

解析&代码

题目大意

给出n,m,k,求贷款者向银行支付的利率p,使得:

i=1km(1+p)i=n

按百分比形输出,精确到小数点后一位。

解析

orz,光是理解题意就理解了半天……果然语文差学OI也很难受。

题目中提到了一句很重要的话:利率按月累计。这是什么意思呢?这是指,假如第一个月的利率为(1+p),那么第二个月就变成了(1+p)2了。那么这两个月,你偿还的金额实际相当于你借得的m1+p+m(1+p)2元。我们已知一共借了n元,那么就能得到上面提到的公式了。

关于如何计算m。首先,根据生活常识利率越大你实际偿还的金额(即你借到的n元)越小。我们对上式移项:

i=1k1(1+p)i=nm

p小于正确答案时,左式就会小于右式。反之左式就会大于右式。因此我们可以根据p的单调性倍增。

我们设f(p)=左式=i=1k1(1+p)i。设当前答案为p,倍增量为k。那么如果f(p)<nm,我们就可以让p加上k,同时将k翻倍。否则将k减半。当k小于某个阈值(即精度)时,此时的p就是答案。

倍增算法有一个好处是,你几乎不用考虑上界(即使银行放超高利贷orz)。并且精度非常容易控制:你只需要将pk初始为非常小的数(比如106),然后退出条件为k是否大于1011即可。

倍增的复杂度与二分相同,为O(KlogN)。其中N为答案除以精度,K为分期付款总天数。

代码

#include <bits/stdc++.h>
using namespace std;
int main()
{
double a,b,c;
cin >> a >> b >> c;
//l和r分别表示利率的最小值和最大值,也就是初始范围。
double l=0, r=1000,mid=0;
//double数据类型,相差小于0.0001结束循环,避免多次循环
while(l<r-0.0001)
{
mid=(l+r)/2;//mid为范围的中间值。
double w=a;//w为未还的总钱数。
for(int i=0;i<c;i++)//模拟还钱过程。
{
w=w-b+w*(mid/100);
}
if(w>0.0001)//检验在这个利率下,是否将钱还完。
{
r=mid;//钱未还完,利率偏大,将范围最大值设置为中间值。
}
else{
l=mid;//钱还多了,利率偏小,将范围最小值设置为中间值。
}
}
cout << fixed << setprecision(1) << round(l*10)/10;
return 0;
}
posted @   Momo·Trace  阅读(76)  评论(0编辑  收藏  举报
评论
收藏
关注
推荐
深色
回顶
收起
点击右上角即可分享
微信分享提示