洛谷Day1--P1102 A-B数对 P1163 银行贷款

目录

一、引言

二、题目及题解

题目一:P1102 A-B 数对

题目链接

题解:哈希

 题目二:P1163 银行贷款

题目链接

题解:二分 

三、小结


一、引言

今天是周日,代码随想录训练营的打卡休息一天。想着刷一点题巩固一下之前的所学,就做了两道洛谷的题,一道用的哈希(也可以二分,个人感觉麻烦一点),一道用的二分,都是之前打卡学过的知识进行运用。今天的两道题总体而言比较简单,不过第二道题涉及一点财经知识(开始我就理解错了,以为每年增量一样,做成简单数学题了),做完就当是对之前所学进行回顾了。

这里我们直接看题。

二、题目及题解

题目一:P1102 A-B 数对

题目链接

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 银行贷款

题目链接

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的值四舍五入到小数点后一位。

三、小结

今天的练习就到此结束了,做的题不多,也当做放松一下。明天将继续代码随想录训练营的打卡,洛谷刷题这个系列的更新就暂时停下,不过也是希望自己能一直坚持刷各种的题。最后,我是算法小白,但也希望终有所获。

  • 22
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值