要知道什么是‘递归’.|

2c237c6

园龄:1年4个月粉丝:2关注:0

ACM题解Day8 | 最小公倍数 GCD 模块 |最小共倍数,等差数列,后缀表达式

学习目标:

博主介绍: 27dCnc
专题 : 数据结构帮助小白快速入门算法
👍👍👍👍👍👍👍👍👍👍👍👍
☆*: .。. o(≧▽≦)o .。.:*☆

Github今日打卡
fggh

  • ACM题解

学习时间:

  • 周一至周五晚上 7 点—晚上9点
  • 周六上午 9 点-上午 11 点
  • 周日下午 3 点-下午 6 点

学习内容:

  1. 最小共倍数
  2. 等差数列
  3. 后缀表达式

内容详细:

最小共倍数

题目考点: 最小共倍数 最大共约数

在这里插入图片描述

题目要点: 理解 最大公约数 和 理解 最小公倍数的关系

辗转相除最大公约数

辗转相除法(又称欧几里德算法)用于求解两个整数的最大公约数(Greatest Common Divisor,简称 GCD),也可以扩展为求解多个整数的最大公约数。

辗转相除法的基本思想是通过一系列的除法操作,将两个整数逐渐缩小为它们的余数,直到余数为 0。最后一个非零余数就是这两个整数的最大公约数。

具体步骤如下:

  1. 将较大的整数除以较小的整数,得到商和余数。
  2. 如果余数为 0,则较小的整数就是最大公约数。
  3. 如果余数不为 0,则将较小的整数作为被除数,余数作为除数,继续执行第一步。
  4. 重复执行步骤 1 和 3,直到余数为 0,最后一个非零余数就是最大公约数。

辗转相除法的优点是简单、高效,能够快速求解两个整数的最大公约数。它在数论和计算机科学中被广泛应用,例如在分数的化简、判断两个数是否互质、模运算的逆元计算等场景中都有重要的作用。

辗转相除法代码

inline int gcd(int a, int b) { //经典代码
    int r;
    while(b > 0) {
        r = a % b;
        a = b;
        b = r;
    }
    return a;
}

递归

int gcd(int a,int b) {
    return b > 0 ? gcd(b,a%b):a;
}

最小公倍数

代码

int lcm(int a, int b) {
    return (a * b) / gcd(a, b);
}

代码解释

这段代码是用于计算两个整数 a 和 b 的最小公倍数(Least Common Multiple,简称 LCM)。

在这段代码中,调用了一个名为 gcd 的函数,用于计算 a 和 b 的最大公约数。最小公倍数可以通过以下公式计算得到:

LCM(a, b) = a * b / GCD(a, b)

因此,这段代码的作用就是先计算 a 和 b 的最大公约数,然后通过上述公式求解它们的最小公倍数。

具体来说,这个函数首先将 a 和 b 相乘得到它们的乘积,然后除以它们的最大公约数,从而得到它们的最小公倍数。

最小公倍数在数学和计算机科学中都有广泛的应用,例如在分数的通分、同时执行多个周期性任务等场景中都需要用到最小公倍数。

综上所述题目详细代码

#include<bits/stdc++.h>
#define Run 0
#define endl "\n"
#define N 100005
using unl = __int128_t;
using ll = long long;
using namespace  std;

class Solution {
public: //就是一个数的所有公倍数
     void solve() {
        int n,m; cin >> n >> m;
        cout << lcm(n,m) << endl;
    }
    
    int gcd(int a,int b) {
    return b > 0 ? gcd(b,a%b):a;
	}
	
    int lcm(int a, int b) {
        return (a * b) / gcd(a, b);
    }
};

signed main() {

    cin.tie(0) -> ios::sync_with_stdio(0);
    cout.tie(0) -> ios::sync_with_stdio(0);

    #if Run
        int _;cin>>_;while(_--) Solution().solve();
    #else
        Solution().solve();
    #endif

    return 0;
}

等差数列

题目考点: 最小共倍数
在这里插入图片描述
掌握: 最小公倍数 等差数列的 d 为各项间最小公倍数

代码

#include<bits/stdc++.h>
#define Run 0
#define endl "\n"
#define N 100005
using unl = __int128_t;
using ll = long long;
using namespace  std;

class Solution {
public: 
    int gcd(int a,int b)  //欧几里得算法 
    {
        return b?gcd(b,a%b):a; //b不为0 
    }
     void solve() {
        int n; cin >> n;
        int a[n + 5];
        for (int i = 1; i <= n; i++) {
            cin >> a[i];
        }
        sort(a + 1, a + 1 + n);
        int d = 0;
        for (int i = 2; i <= n; i++) {
            d = gcd(d, a[i] - a[i - 1]);
        }
        if (d) cout << (a[n] - a[1] )/ d + 1 << endl; // 数列长度,当前最大项即最后一项
        else cout << n << endl; //如果d == 0 则说明只有n项无法确定有多少项就n项
    }
};


signed main() {

    cin.tie(0) -> ios::sync_with_stdio(0);
    cout.tie(0) -> ios::sync_with_stdio(0);

    #if Run
        int _;cin>>_;while(_--) Solution().solve();
    #else
        Solution().solve();
    #endif

    return 0;
}

初识前缀和 后缀表达式

题目考点: 前缀和
在这里插入图片描述

思路:前缀和

代码

#include<bits/stdc++.h>
#define Run 0
#define endl "\n"
#define N 100005
using unl = __int128_t;
using ll = long long;
using namespace  std;

class Solution {
public: 
     void solve() {
        ll n,m; 
        while(cin >> n >> m) {
            vector<ll>a(n + m + 100); //用于储存数据
            ll res = 0; //初始化当前值
            for (ll i = 1; i <= n + m + 1; i++) cin >> a[i]; //输入值
            sort(a.begin() + 1,a.begin() + n + m + 2); //排序保证减的最小化
            if(m == 0) { 
                for (ll i = 1; i <= n + m + 1; i++)  res += a[i]; //如果没有负号则为前缀和
            } else { //不为0
                res = a[n + m + 1] - a[1]; //向减去最小的那个然后前缀和
                for (ll i = 2; i <= n + m; i++) res += a[i];
            }
            cout << res << endl; //最后输出答案
        }
    }
};


signed main() {

    cin.tie(0) -> ios::sync_with_stdio(0);
    cout.tie(0) -> ios::sync_with_stdio(0);

    #if Run
        int _;cin>>_;while(_--) Solution().solve();
    #else
        Solution().solve();
    #endif

    return 0;
}

这段代码实现了一个解题类Solution,其中包含一个solve()函数用于解决特定问题。让我们详细解析一下代码的功能:

  1. 宏定义部分:

    • 定义了宏Run为0,表示不运行多组测试数据。
    • 定义了换行符endl为"\n"。
    • 定义了常量N为100005。
  2. 类定义部分:

    • Solution类中定义了一个solve()函数,用于解决问题。
  3. solve()函数:

    • 该函数首先读入两个整数n和m。
    • 然后定义了一个大小为n+m+100的vector数组a,用来存储输入的n+m+1个整数。
    • 接着使用循环将n+m+1个整数读入数组a中。
    • 对数组a进行从第2个元素到第n+m+1个元素的排序。
    • 根据m的值,计算出结果res:
      • 若m为0,则将所有元素相加得到结果。
      • 若m不为0,则结果为最大元素减去最小元素再加上除去最大最小元素外的其他元素之和。
    • 最后输出结果res。
  4. 主函数main():

    • 设置了输入输出流的同步。
    • 根据宏定义Run的取值,决定是否进行多组测试数据的输入输出。
    • 如果Run为真,则会读入一个整数_,然后循环_次调用Solution的solve()函数。
    • 否则直接调用一次solve()函数。

总体来说,这段代码的功能是输入一组数据,根据一定规则计算结果并输出。如果有具体的问题描述,可以更清楚地理解代码的作用。


学习产出:

  • 技术笔记 2 遍
  • CSDN 技术博客 3 篇
  • 习的 vlog 视频 1 个

在这里插入图片描述

重磅消息:

GTP - 4 最新版接入服务他来了 点击链接即可查看详细

GTP - 4 搭建教程

🔥如果此文对你有帮助的话,欢迎💗关注、👍点赞、⭐收藏、✍️评论,支持一下博主~

本文作者:2c237c6

本文链接:https://www.cnblogs.com/27dCnc/p/18568629

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   2c237c6  阅读(13)  评论(0编辑  收藏  举报  
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起