目录
一、引言
今天是周日,代码随想录训练营的打卡休息一天。想着刷一点题巩固一下之前的所学,就做了两道洛谷的题,一道用的哈希(也可以二分,个人感觉麻烦一点),一道用的二分,都是之前打卡学过的知识进行运用。今天的两道题总体而言比较简单,不过第二道题涉及一点财经知识(开始我就理解错了,以为每年增量一样,做成简单数学题了),做完就当是对之前所学进行回顾了。
这里我们直接看题。
二、题目及题解
题目一:P1102 A-B 数对
题目链接
# A-B 数对
## 题目背景
出题是一件痛苦的事情!
相同的题目看多了也会有审美疲劳,于是我舍弃了大家所熟悉的 A+B Problem,改用 A-B 了哈哈!
## 题目描述
给出一串正整数数列以及一个正整数 $C$,要求计算出所有满足 $A - B = C$ 的数对的个数(不同位置的数字一样的数对算不同的数对)。
## 输入格式
输入共两行。
第一行,两个正整数 N,C。
第二行,N个正整数,作为要求处理的那串数。
## 输出格式
一行,表示该串正整数中包含的满足 A - B = C 的数对的个数。
## 样例
### 样例输入
4 1
1 1 2 3### 样例输出
3## 提示
对于 75%的数据,1≤N≤2000。
对于 100% 的数据,1≤N≤2×10^5,0≤a<2^30,1≤C<2^30。
题解:哈希
先说说哈希的做法,题目要求我们寻找 a - b = c 的个数,其中a,b都是数组的元素,c相当于是给定的值,然后这道题要求下标不同时,数据相同算不同情况。这里我们就可以想到哈希,哈希的作用就是记录某个数出现的次数,我们先把a(这里就是数组的元素a[i])全部存入哈希表中,并记录下每个元素出现的次数(这个思想就是之前打卡的242. 有效的字母异位词 - 力扣(LeetCode)),然后我们再遍历整个哈希表寻找b(b就是a - c),寻找到的符合的b的个数的和就是满足a - b = c 的情况数。(这里可以仔细想一下,因为a始终比b大,这样刚好可以寻找到满足的所有情况)
代码如下:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll; //题目要求数据较大:用long long
ll n,c;
ll a[200004];
ll cnt;
int main()
{
cin>>n>>c;
unordered_map<ll,ll> hash; //key为元素,value为元素出现的次数(个数)
for(int i = 0; i < n; i++)
{
cin>>a[i];
hash[a[i]]++;
}
for(int i =0; i < n; i++)
{
cnt += hash[a[i]-c]; //加上满足情况的b出现的次数(个数)
}
cout<<cnt;
return 0;
}
题目二:P1163 银行贷款
题目链接
# 银行贷款
## 题目描述
当一个人从银行贷款后,在一段时间内他(她)将不得不每月偿还固定的分期付款。这个问题要求计算出贷款者向银行支付的利率。假设利率按月累计。
## 输入格式
三个用空格隔开的正整数。
第一个整数表示贷款的原值 $w_0$,第二个整数表示每月支付的分期付款金额 $w$,第三个整数表示分期付款还清贷款所需的总月数 $m$。
## 输出格式
一个实数,表示该贷款的月利率(用百分数表示),四舍五入精确到 $0.1\%$。
数据保证答案不超过 300.0%。
## 样例 #1
### 样例输入 #1
```
1000 100 12
```### 样例输出 #1
```
2.9
```数据保证,1≤w0,w≤2^31−1 ,1≤m≤3000。
题解:二分
这里我们先看代码(看注释先理解):
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int main()
{
double a, b, c; //a为贷款原值,b为每月还款,c为还款月数
cin>>a>>b>>c;
double left = 0, right = 500, mid = 0; //left,right表示利率存在的最小值和最大值(题目说明不超过300%,我们取个比300大的数)
while (left < right - 0.0001) //在浮点数运算中,由于精度问题,直接比较两个浮点数是否相等是不准确的,故通常会设一个小的阈值(如0.0001),当两个浮点数的差值小于这个阈值时,就认为它们是“相等”的。
{
mid = left + (right - left) / 2; //注意这里不能用>>1(这里数据为浮点数)
double w = a; //w为未还的总钱数,初始化为a,即贷款原值
for (int i = 0; i < c; i++)
{
w = w - b + w * (mid / 100);
}
if (w > 0.0001) //检验在这个利率下,是否将钱还完。
right = mid; //钱未还完,利率偏大
else
left = mid; //钱还多了,利率偏小
}
printf("%0.1f",round(mid * 10) / 10); //由于题目要求月利率要四舍五入到0.1%,round(mid * 10) / 10 可将mid的值四舍五入到小数点后一位。
return 0;
}
这个题本身难度不大,就一个很常规的二分思想。但首先我们要搞懂题意,利率按月累计是指什么?这里我们可以知道:每月利息 = 贷款余额 × 月利率。这里的贷款余额可能会随着每月的还款而减少,因此每月的利息也可能会有所不同。我们将a作为贷款原值,b作为每月还款,c作为还款月数,将未还款数记为w,可以得到每个月未还款数依次变为:w = w - b + w * (mid / 100);这样搞清楚这一点,就比较好理解了。
几个注意点:
1.浮点数的二分循环条件: while (left < right - 0.0001) ,原因:在浮点数运算中,由于精度问题,直接比较两个浮点数是否相等是不准确的,故通常会设一个小的阈值(如0.0001),当两个浮点数的差值小于这个阈值时,就认为它们是“相等”的。
2.round()函数的作用:用于将浮点数四舍五入到最接近的整数。
在这里,round(mid * 10) / 10 可将mid的值四舍五入到小数点后一位。
三、小结
今天的练习就到此结束了,做的题不多,也当做放松一下。明天将继续代码随想录训练营的打卡,洛谷刷题这个系列的更新就暂时停下,不过也是希望自己能一直坚持刷各种的题。最后,我是算法小白,但也希望终有所获。
标签:10,题目,P1102,##,浮点数,数对,mid,哈希,洛谷 From: https://blog.csdn.net/2303_79786049/article/details/140753419