zoukankan      html  css  js  c++  java
  • [luogu p1163] 银行贷款

    传送门

    银行贷款

    题目描述

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

    输入输出格式

    输入格式

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

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

    输出格式

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

    输入输出样例

    输入样例 #1

    1000 100 12
    

    输出样例 #1

    2.9
    

    分析

    二分答案做法

    此题我想到了两种思路,先从第一个开始说吧,既然是从二分题单来的,就先说说二分答案做法。

    二分答案做法其实就是二分利率,都是套板子的事,问题是check函数怎么写。

    首先我们来看一下利率公式:

    [sum^k_{i=1}dfrac{m}{(1 + p)^i} = n ]

    其中原题中的三个值:

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

    就分别对应(n, m, k)

    现在我们把这个式子变一下形。

    [sum^k_{i=1}dfrac{1}{(1 + p)^i} = dfrac{n}{m} ]

    等式左边其实就是公比为(dfrac{1}{1 + p})的等比数列求和。利用等比求和公式(S_n = a_1dfrac{1 - q ^ n}{1 - q})
    可得:

    [egin{aligned}sum^k_{i=1}dfrac{1}{(1 + p)^i} & = dfrac{1}{1 + p} imes dfrac{1 - (dfrac{1}{1 + p}) ^ k}{1 - dfrac{1}{1 + p}}\& = dfrac{1 - (dfrac{1}{1 + p}) ^ k}{(1 + p) imes (1 - dfrac{1}{1 + p})}\ & = dfrac{1 - (dfrac{1}{1 + p}) ^ k}{p}end{aligned} ]

    此时原式可以转化为:

    [dfrac{1 - (dfrac{1}{1 + p}) ^ k}{p} = dfrac{n}{m} ]

    两边同( imes p)

    [1 - (dfrac{1}{1 + p}) ^ k = dfrac{n}{m} imes p ]

    两边再同时(- 1),然后( imes (-1))

    [(dfrac{1}{1 + p}) ^ k = 1 - dfrac{n}{m} imes p ]

    这样我们就能写出check函数了:

    bool check(double x) {
        return pow(1.0 / (1.0 + x), k) >= 1 - n / m * x;
    }
    

    小提示:pow函数需要#include <cmath>使用,pow(n, k)是n的k次方的意思。至于check函数为啥用大于等于而不是等于,是为了二分缩小范围服务的。不懂没关系看代码你就懂了。

    check函数写完后就简单了,二分整体代码见一会的总体代码部分。

    哦对了关于这个二分的边界问题我要说明一下,此题中存在(p > 1)的情况,所以右边界不能定为1。

    相信有的同学想问了,蟹蟹这里也没有说利率的范围啊,右边界不好定怎么办?

    就是因为这个,我思考了另一种方法:

    倍增做法

    用倍增写这道题也是不错的选择。check函数还是那个check函数,整体都差不多,只是main函数中的二分答案变成了倍增而已,没什么好说的。

    但是这种方案不用定右边界,完美解决了这个问题。

    就这样吧,上代码。

    代码

    二分答案做法

    /*
     * @Author: crab-in-the-northeast 
     * @Date: 2020-06-16 09:18:57 
     * @Last Modified by: crab-in-the-northeast
     * @Last Modified time: 2020-06-16 15:28:56
     */
    //二分答案
    #include <iostream>
    #include <cstdio>
    #include <iomanip>
    #include <cmath>
    
    const double eps = 1e-10;
    
    double n, m, k;
    bool check(double x) {
        return pow(1.0 / (1.0 + x), k) >= 1 - n / m * x;
    }
    
    int main() {
        std :: cin >> n >> m >> k;
        double l = 0, r = 10086;
        while (r - l >= eps) {
            double mid = (l + r) / 2;//不能用位运算了啊啊啊啊啊啊啊啊暴风哭泣
            if (check(mid)) r = mid;
            else l = mid;
        }
    
        std :: cout << std :: fixed << std :: setprecision(1) << l * 100 << std :: endl;
        return 0;
    }
    
    

    倍增做法

    /*
     * @Author: crab-in-the-northeast 
     * @Date: 2020-06-16 09:18:57 
     * @Last Modified by: crab-in-the-northeast
     * @Last Modified time: 2020-06-16 15:27:24
     */
    //倍增
    #include <iostream>
    #include <cstdio>
    #include <iomanip>
    #include <cmath>
    
    const double eps = 1e-10;
    double n, m, k;
    
    bool check(double x) {
        return pow(1.0 / (1.0 + x), k) >= 1 - n / m * x;
    }
    
    int main() {
        std :: cin >> n >> m >> k;
        double ans = 0;
        double add = 0.1;
        while (add >= eps) {
            if (!check(ans + add)) {//注意这里是!check哦,原因自己想想
                ans += add;
                add *= 2.0;
            }
            else
                add /= 2.0;
        }
    
        std :: cout << std :: fixed << std :: setprecision(1) << ans * 100 << std :: endl;
        return 0;
    }
    

    评测记录

    评测记录

  • 相关阅读:
    java位运算
    AmCharts realtime flush example //add by liuwei 20120929
    配置Linux—LVS (DR)
    LVS(Linux Virtual Server) 学习笔记
    一个由sizeof引出的有意思的问题
    关于IsDebuggerPresent
    我的第一个python程序
    听Robert C. Richardson的报告会很失望
    杯具了,为啥不去tencent的实习生招聘呢
    通过信号量机制解决生产者消费者问题的模拟程序
  • 原文地址:https://www.cnblogs.com/crab-in-the-northeast/p/luogu-p1163.html
Copyright © 2011-2022 走看看