P1163 银行贷款(小数二分)

发布时间 2023-03-22 22:43:19作者: HelloHeBin

变量命名如下:
\(n\) 表示贷款的原值,
\(m\) 表示每月支付的分期付款金额,
\(k\) 表示分期付款还清贷款所需的总月数。
\(p\) 表示贷款的月利率

\(1\) 月利率为 \((1+p)\),其还款金额 \(m\) 相当于借款金额 \(\frac{m}{1+p}\)

\(2\) 月利率为 \((1+p)^2\),其还款金额 \(m\) 相当于借款金额 \(\frac{m}{(1+p)^2}\)

\(3\) 月利率为 \((1+p)^3\),其还款金额 \(m\) 相当于借款金额 \(\frac{m}{(1+p)^3}\)

....

\(k\) 月利率为 \((1+p)^k\),其还款金额 \(m\) 相当于借款金额 \(\frac{m}{(1+p)^k}\)

其总共还款金额 \(k*m\) 相当于借款金额 \(s = \sum_{i=1}^{k} \frac{m}{(1+p)^i}\)

于是有公式, \(s = \sum_{i=1}^{k} \frac{m}{(1+p)^i}=n\)

所以问题转化为找一个合法的 \(p\),使其满足上述公式。

假定 \(p\) 的可取范围为 \([0,10]\),小数二分该区间即可。

如果 \(s≤n\),则证明 \(p\) 需要降低 --- 即取左区间 \(r=mid\)

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const double eps=1e-4;
double n,m,k;

// 检查利率为 x 时,还款是否 <=n.
bool chk(double x){
    double s=0, p=1;
    for(int i=1; i<=k; i++){
        p *= (1+x);
        s += m/p;
    }
    return s<=n;
}
int main() {
    scanf("%lf%lf%lf",&n,&m,&k);
    double l=0,r=10;
    while(r-l > eps){
        double mid=(l+r)/2;
        if(chk(mid)) r=mid;
        else l=mid;
    }
    printf("%.1lf",l*100);
    return 0;
}