P1163 银行贷款

264 阅读1分钟

题目链接

题目描述

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

输入格式

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

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

输出格式

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

输入输出样例

输入 #1

1000 100 12

输出 #1

2.9

说明/提示

数据保证,1≤ 贷款的原值,分期付款金额  2311≤2^{31}-1, 1 月数30001≤ 月数 ≤3000。

解题思路

这是一道浮点数二分答案题目,首先对于check()函数,我们来二分月利率p,通过p来计算总钱数并和给出的n进行对比,前者大于等于后者就返回true,并移动左端点来缩小二分区间,否则移动右端点。
核心的就这一小部分。

    for (int i = 1; i <= m; i++)
    {
        k *= (1 + p);
        sum += (x / k);
    }

最后还得注意,浮点数的区间要用double,月利率要用double。 double sum = 0, k=1;最开始我在这里卡了好长时间,结果发现double写成了int,利率p用int的话,小数部分会丢失。
另外二分的while()循环的条件不要写反了,r - l > 1e-4写反的话,就一次也不会循环了。

AC代码

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
#define int long long
#define endl '\n'
typedef long long ll;

double n, x;
int m;
int check(double p) 
{
    double sum = 0, k=1;
    for (int i = 1; i <= m; i++)
    {
        k *= (1 + p);
        sum += (x / k);
    }
    if (sum >= n) return true;
    else return false;
}

signed main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin >> n >> x >> m;
    double l=0, r=800, mid;
    while (r - l > 1e-4)
    {
        mid = (l + r ) /2;
        if (check(mid)) l = mid;
        else r = mid;
    }
    printf("%.1f", mid*100);
    return 0;
}