一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第8天,点击查看活动详情。
题目描述
这是4月8日代码源div2的每日一题。
高利贷 - 题目 - Daimayuan Online Judge
19岁的大学生小 L 家里情况不好,每月固定生活费不足以买一部苹果手机。当他得知有贷款机构可以贷小额贷款并且可以分期等额还款,每月只需要还几百块时,在虚荣心的驱使下他开始自己的贷款之旅。
贷款机构声称利率按月累计,贷款人在贷款期间每月偿还固定的分期付款金额。
给出小 L 贷款的原值为 n,分期付款金额 m 和分期付款还清贷款所需的总月数 k,求该贷款的月利率 p。
输入格式
三个用空格隔开的正整数 n,m,k,含义如上述所示。
输出格式
一个实数 p,表示该贷款的月利率(用小数表示),和标准输出绝对值不超过10^(−6)即可。
数据范围
1≤n,m≤10^6,1≤k≤300
0≤p≤5,
n≤m×k
输入样例1
1000 1200 1
输出样例1
0.200000
样例解释
对于第一组样例,小 L 贷款了 1000
元,并在一个月后支付 1200 元还清了贷款。因此计算月利率 p 的公式为 1000×(1+p)=1200 或 1200/(1+p)=1000,求出 p=0.200000。
第 k 个月偿还的金额只相当于 100/(1+p)^k 元的初始金额
问题解析
浮点二分。
我们可以在0~5的区间内二分枚举p(当然是以浮点数的形式),浮点二分和一般的二分结束条件不太一样,一般的结束条件是l<r,但由于这是浮点数,显然是不适用的,浮点二分的结束条件一般是r-l>(与标准答案最多能相差的精度),在这题就是r-l>1e(-6)。
然后就是用枚举的p来计算。提示里说了:第 k 个月偿还的金额只相当于 100/(1+p)^k 元的初始金额。那么这就是个等比数列的前n项和了,计算一共k个月(0~k)偿还的金额是否等于n即可。如果少了说明p小了,如果多了说明p大了。
AC代码
#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
#include<math.h>
#include<set>
#include<numeric>
#include<string>
#include<string.h>
#include<iterator>
#include<map>
#include<unordered_map>
#include<stack>
#include<list>
#include<queue>
#include<iomanip>
#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
#define endl '\n';
typedef long long ll;
typedef pair<int, int> PII;
const int N = 1050;
double check(double mid, int k, int m)
{
double res = 0,p=1+mid;
for (int i = 1; i <= k; i++)
{
res += m / p;
p *= (1 + mid);
}
return res;
}
int main()
{
ll n, m, k;
cin >> n >> m >> k;
double l = 0, r = 5;
while (r - l >= 1e-8)
{
double mid = (r + l) / 2;
double money = check(mid,k,m);
if (money > (double)n)l = mid;
else r = mid;
}
cout << fixed << setprecision(6) << l << endl;
return 0;
}