银行贷款

GitHub跳转原题关系图返回列表

二分月利率,逐月模拟计息与还款后的剩余本金,使最终余额逼近零。

OJ: luogu

题目 ID: P1163

难度:普及/提高-

标签:二分答案模拟数学python

日期: 2026-07-16 17:49

题意

已知贷款本金、每月还款额和还清所需月数,求按月累计的利率,以百分数输出并保留一位小数。

思路

给定小数形式的月利率 rate,每个月结束后的余额是:

text
balance = balance * (1 + rate) - payment

利率越高,最后剩余余额越大。于是可在题目保证的 [0,3] 范围内二分:最终余额不大于零时利率还可以提高,否则应降低。

浮点二分固定执行 100 次,精度足够覆盖 0.1% 的输出要求。

Python 知识

  • Python 可以直接混合整数输入和浮点计算,无需显式类型转换本金。
  • 固定次数浮点二分结构稳定,不依赖 while right-left > eps 的阈值选择。
  • f"{left * 100:.1f}" 同时完成小数转百分数和保留一位小数。
  • /home/rainboy/mycode/hugo-blog/content/program_language/python/oj_input_output_cheatsheet.md:浮点格式化输出。

代码

python
principal, payment, months = map(int, input().split())


def remaining_balance(rate):
    balance = principal
    for _ in range(months):
        balance = balance * (1 + rate) - payment
    return balance


left, right = 0.0, 3.0
for _ in range(100):
    middle = (left + right) / 2
    if remaining_balance(middle) <= 0:
        left = middle
    else:
        right = middle

print(f"{left * 100:.1f}")
cpp
/**
 * Author by Rainboy blog: https://rainboylv.com github: https://rainboylvx
 * rbook: -> https://rbook.roj.ac.cn  https://rbook2.roj.ac.cn
 * rainboy的学习导航网站: https://idx.roj.ac.cn
 * create_at: 2026-07-27 00:00
 * update_at: 2026-07-27 00:00
 */

/* P1163 银行贷款 */
/* 二分月利率,逐月模拟还款后剩余本金,使最终余额接近零。 */

#include <bits/stdc++.h>
using namespace std;

double principal; // 本金
double payment;   // 每月还款额
int months;       // 还清月数

// 给定月利率 rate(小数),计算最终剩余本金
double remaining(double rate) {
    double balance = principal;
    for (int i = 1; i <= months; i++) {
        balance = balance * (1 + rate) - payment;
    }
    return balance;
}

int main() {
    cin >> principal >> payment >> months;

    // 利率越高,最终剩余本金越大,单调递增
    double l = 0.0, r = 3.0;
    // 浮点二分固定 100 次,精度足够
    for (int i = 1; i <= 100; i++) {
        double mid = (l + r) / 2;
        if (remaining(mid) <= 0) {
            l = mid; // 利率还能更高
        } else {
            r = mid;
        }
    }

    // 输出百分数,保留一位小数
    printf("%.1f\n", l * 100);
    return 0;
}

复杂度

每次判定模拟 m 个月,总时间复杂度为 O(100m)=O(m)O(100m)=O(m),空间复杂度为 O(1)O(1)

总结

先写出“给定利率后余额如何变化”,再观察最终余额对利率单调递增,就能把反求利率转成浮点二分。