题解 | 小红的 gcd

小红的 gcd

https://www.nowcoder.com/practice/9a5ac1e1c2fb4f8d85595a52ff0a00fa

思路

先看一眼题,gcd,再看一眼数据,a 的十进制位数最大可以达到1e6!

这意味着a可能非常大! !超过了long long类型所能表示的范围。

由于a过大,我们不能直接使用标准的欧几里得算法,因为a无法作为一个long long或者int类型传入计算。

核心处理

当 a是一个大数时, 欧几里得算法的操作仍然是可行的,因为:

  1. 大整数 a可以用一个字符串str来表示。
  2. 对一个大整数 a 求模 b,实际上就是不断地对 a 的各位数字进行处理,而中间的余数永远不会超过 b-1,

代码构思

步骤 1:求大数a对小数b的模

我们可以通过模拟长除法的过程来实现大数模小运算。

a的字符串表示为 str

初始化余数res

遍历字符串str中的每一个数字字符 c

将当前余数 res乘以 10,并加上新的数字 c 对应的整数值,对结果进行求模 。

经过遍历,最终得到的 res就是 a(mod)b的结果。

步骤 2:使用欧几里得算法求gcd(a,b)

根据 ,现在问题转化为了求两个标准整数resb 的最大公约数。我们可以使用标准的欧几里得算法:

ACnode

#include <bits/stdc++.h>
using namespace std;
#define int long long
//万恶的dill
int gcd(int x, int y)
{
    return y == 0 ? x : gcd(y, x % y);
}/*用三目运算符表示欧几里得算法,等同于下面这个
    if (y == 0) 
    {
        return x;
    }
    return gcd(y, x % y);
    当然,也可以用迭代实现(我认为三目更好写一些())
    while (y) 
    {
        x %= y;
        swap(x, y);
    }
    return x;*/
void solve()
{
    string str;
    int b;
    cin >> str;// 输入大整数a (用字符串读取)
    cin >> b;
    int res = 0;
    for (char c : str)// 遍历大数a的每一位
    {
        res = (res * 10 + (c - '0')) % b;
        // 1. 将前一位的余数 * 10,并加上当前位数字的值
        //    (res * 10 + (c - '0'))
        // 2. 对结果进行求模 b,保证 res 始终在 [0, b-1] 范围内
    }
    int ans = gcd(res, b);
    cout<<ans<<endl;
}

signed main()
{
    int t = 1;
    //cin>>t;
    //个人码风,方便调试
    while (t--)
    {
        solve();
    }
    return 0;
}

全部评论

相关推荐

爱吃烤肠的牛油最喜欢...:50K是ssp了估计,ssp的人家多厉害都不用说,每年比例大概在百分之5左右
点赞 评论 收藏
分享
hwwhwh:同双非,有大厂实习其实也没啥用,主要看运气,等就行了
点赞 评论 收藏
分享
评论
7
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务