计蒜客题解——T1871:银行贷款

题目相关

题目链接

计蒜客,https://nanti.jisuanke.com/t/T1871。

题目描述

蒜头君从银行贷款了 1000 元钱,月利率为 10%,三个月内分三期还款,那他每次要还款 402.11 元。银行告诉他是这么算的:\frac{402.11}{1.1}+\frac{402.11}{1.1^{2}}+\frac{402.11}{1.1^{3}}\approx 1000

现在已知总贷款数 x 元,每个月还贷 y 元,一共贷款 n 个月,要求计算出贷款者向银行支付的利率,假设利率按月累计。

输入格式

三个用空格隔开的正整数 x,y,n (1≤x,y≤10^5,1≤n≤20),分别表示总贷款数,每月还贷数目,一共的月份。

输出格式

一个实数,表示该贷款的月利率(用百分数表示),四舍五入精确到 0.1%。答案保证不超过 1000%。

样例输入

1000 100 12

样例输出

2.9

题目分析

题目要求

告诉总贷款数 x 元,每个月还贷 y 元,一共贷款 n 个月,要求计算出贷款者向银行支付的利率,假设利率按月累计。从样例输出可以看出,这就是一个标准的浮点数二分题。

样例数据分析

浮点数二分数据分析以前做过,具体可以参考这篇文章,https://blog.csdn.net/justidle/article/details/104620745。这里就不分析了。

而且从题目可以看出,最小的月利率是 0.1%,最大的月利率是 1000%。也就是左边界是 0.001,右边界是 10。精度呢?题目要求四舍五入到 0.1%,也就是小数点后 3 位,因此 EPS 可以去 1e-5 就可以满足要求了。

编程思路

1、编写 check 函数。就是根据题目给的计算公式,用 mid 为利率,计算 n 个月后有多少钱。如果按照 mid 利率算出的钱大于总贷款数 x,则缩小利率。否则放大利率。

2、读入数据。

3、从 left=0.001 到 right=10,套用浮点数二分查找模板,快乐的二分吧。

AC 参考代码

#include 
using namespace std;

double x;//总贷款数
double y;//每个月还贷
double n;//贷款月份

//以x为利率计算 n 年
bool check(double mid) {
    double ans=0;
    for (int i=1; i<=n; i++) {
        ans += y/pow(1+mid, i);
    }

    if (ans>x) {
        return true;
    } else {
        return false;
    }
}

int main() {
    //读入数据
    cin>>x>>y>>n;

    //浮点数二分
    double left = 0.001;
    double right = 10;
    const double EPS = 1e-5;
    double mid;
    while (right-left>EPS) {
        mid = (left+right)/2;

        if (check(mid)) {
            left = mid;
        } else {
            right = mid;
        }
    }

    printf("%.1lf\n", left*100);

    return 0;
}

时间复杂度

O(nlogn)。

你可能感兴趣的:(OJ题解,#,计蒜客题解)