gcd以及多数gcd

解决gcd与lcm计算中的常见问题
本文详细阐述了如何解决gcd(最大公约数)和lcm(最小公倍数)计算中遇到的问题,包括提供简洁的计算方法以及如何在处理多个数时避免溢出。通过实际代码示例展示了解决思路。
部署运行你感兴趣的模型镜像

以前曾经因为多数gcd被坑了好几次。终于冷静下来找时间把这个坑给填了。

然而只是一些思维上简单的思考而已。

没什么多说的。直接上代码

1.给出一个最简单的gcd写法。

2.多个数的gcd其实也很简单,最重要的是后续求值的时候是否除掉了先前的gcd,下边的写法乘,除,再乘是为了防止溢出。

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
using namespace std;
int i,min,s,n,x,y;
int gcd(int a, int b) {//单纯的简单写法的gcd
	return b==0 ? a : gcd(b, a%b);
}
int main()
{
    while(cin>>n)
    {
        cin>>x;
        for(i=1; i<n; i++)
        {
            cin>>y;
            x=(x/gcd(x,y)*y/gcd(x,y))*gcd(x,y);//多个数的gcd
        }
        cout<<x<<endl;
    }
    return 0;
}

lcm就不再赘述,都是一样的。

您可能感兴趣的与本文相关的镜像

Stable-Diffusion-3.5

Stable-Diffusion-3.5

图片生成
Stable-Diffusion

Stable Diffusion 3.5 (SD 3.5) 是由 Stability AI 推出的新一代文本到图像生成模型,相比 3.0 版本,它提升了图像质量、运行速度和硬件效率

在 C++ 中,计算两个数的 **最大公约数(GCD, Greatest Common Divisor)** 可以使用以下方法: --- ### **方法 1:使用 C++17 的 `std::gcd`(推荐)** C++17 标准库引入了 `<numeric>` 头文件中的 `std::gcd`,可以直接计算两个整数的 GCD。 ```cpp #include <iostream> #include <numeric> // 包含 std::gcd int main() { int a = 48, b = 18; std::cout << "GCD of " << a << " and " << b << " is " << std::gcd(a, b) << std::endl; return 0; } ``` **输出**: ``` GCD of 48 and 18 is 6 ``` **说明**: - `std::gcd` 适用于 **C++17 或更高版本**。 - 支持 `int`、`long`、`long long` 等整数类型。 - 如果传入负数,`std::gcd` 会返回其绝对值的 GCD。 --- ### **方法 2:手动实现欧几里得算法(兼容旧标准)** 如果使用的是 **C++17 之前的版本**,可以手动实现 **欧几里得算法**(辗转相除法): ```cpp #include <iostream> #include <cstdlib> // 用于 abs() int gcd(int a, int b) { a = std::abs(a); b = std::abs(b); while (b != 0) { int temp = b; b = a % b; a = temp; } return a; } int main() { int a = 48, b = 18; std::cout << "GCD of " << a << " and " << b << " is " << gcd(a, b) << std::endl; return 0; } ``` **输出**: ``` GCD of 48 and 18 is 6 ``` **说明**: - 欧几里得算法的时间复杂度是 **O(log(min(a, b)))**,效率很高。 - 使用 `std::abs` 确保负数也能正确计算。 --- ### **方法 3:递归实现欧几里得算法** 也可以使用递归方式实现: ```cpp #include <iostream> #include <cstdlib> int gcd(int a, int b) { a = std::abs(a); b = std::abs(b); return (b == 0) ? a : gcd(b, a % b); } int main() { int a = 48, b = 18; std::cout << "GCD of " << a << " and " << b << " is " << gcd(a, b) << std::endl; return 0; } ``` **说明**: - 递归版本更简洁,但可能存在栈溢出风险(极少数情况)。 --- ### **方法 4:处理多个数的 GCD** 如果需要计算 **多个数的 GCD**,可以迭代调用 `std::gcd` 或自定义函数: ```cpp #include <iostream> #include <numeric> #include <vector> int multi_gcd(const std::vector<int>& nums) { if (nums.empty()) return 0; int result = nums[0]; for (size_t i = 1; i < nums.size(); ++i) { result = std::gcd(result, nums[i]); if (result == 1) break; // GCD 已经是 1,提前终止 } return result; } int main() { std::vector<int> nums = {48, 18, 30}; std::cout << "GCD of multiple numbers is " << multi_gcd(nums) << std::endl; return 0; } ``` **输出**: ``` GCD of multiple numbers is 6 ``` --- ### **注意事项** 1. **C++17 之前**:如果没有 `std::gcd`,必须手动实现(如方法 2 或 3)。 2. **负数处理**:GCD 始终是非负数,因此计算前应取绝对值。 3. **零值处理**: - `gcd(0, a) = a`(因为 0 能被任何数整除)。 - `gcd(0, 0)` 通常定义为 0(但数学上未定义)。 4. **性能**:欧几里得算法比暴力枚举更高效。 --- ### **完整示例(兼容 C++11/14/17)** ```cpp #include <iostream> #include <vector> #include <numeric> // C++17 的 std::gcd #include <cstdlib> // 用于 abs() // 手动实现 GCD(兼容旧标准) int gcd_manual(int a, int b) { a = std::abs(a); b = std::abs(b); while (b != 0) { int temp = b; b = a % b; a = temp; } return a; } int main() { int a = 48, b = -18; // C++17 方式 #ifdef __cpp_lib_gcd std::cout << "C++17 gcd: " << std::gcd(a, b) << std::endl; #else std::cout << "Manual gcd: " << gcd_manual(a, b) << std::endl; #endif return 0; } ``` --- ### **总结** | 方法 | 适用场景 | 优点 | 缺点 | |------|---------|------|------| | `std::gcd` (C++17) | C++17 或更高版本 | 简洁、高效 | 不支持旧标准 | | 手动实现(迭代/递归) | 兼容 C++11/14 | 灵活、可控 | 代码稍长 | | 递归实现 | 喜欢递归风格 | 代码简洁 | 可能栈溢出 | | 多数 GCD | 计算多个数的 GCD | 扩展性强 | 需要额外循环 | **推荐**: - 如果使用 **C++17 或更高版本**,直接用 `std::gcd`。 - 如果使用 **旧标准**,手动实现欧几里得算法。 --- ### **扩展问题** 1. 如何计算 **最小公倍数(LCM)**?(提示:`lcm(a, b) = |a * b| / gcd(a, b)`) 2. 如果输入是 **大整数(如 `long long`)**,如何优化 GCD 计算? 3. 在 C++20 中,`std::gcd` 是否支持更多整数类型(如 `int128_t`)? 4. 如何处理 **浮点数的 GCD**?(提示:通常先转换为整数或使用近似方法) 5. 如果 GCD 计算需要 **避免溢出**,有什么优化方法? 如果有其他问题,欢迎继续提问!
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值