高精度gcd(P2152 SuperGCD)

本文介绍了一种名为更相损减法的算法,用于求解两个大整数的最大公约数。该方法通过不断除以2或进行相减操作来简化问题,直至找到两个数的公共因子。文章提供了详细的算法实现步骤,并附有C++代码示例。

更相损减法

   初始化r=0,求gcd(a,b):

   a!=b时,如果a、b都为偶数,a、b都除以2,r++;如果其中一个为偶数,偶数除以2;如果两个都为奇数,大数减去小数。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
char ar[20000],br[20000];
struct Str
{
    int c[20000],l;
}a,b;
bool equ(Str &a,Str &b)
{
    if(a.l!=b.l)
    return 0;
    for(int i=0;i<a.l;++i)
    {
        if(a.c[i]!=b.c[i])
        return 0;
    }
    return 1;
}
void div(Str &a)
{
    for(int i=a.l-1;i>=0;--i)
    {
        if(a.c[i]&1)
            a.c[i-1]+=10;
        a.c[i]>>=1;
    }
    while(a.c[a.l-1]==0)
        a.l--;
}
bool com(Str &a,Str &b)
{
    if(a.l!=b.l)
        return a.l>b.l;
    for(int i=a.l-1;i>=0;--i)
    {
        if(a.c[i]>b.c[i])
        return 1;
        if(a.c[i]<b.c[i])
        return 0;
    }
}
void mul(Str &a)
{
    int t=0;
    for(int i=0;i<a.l;++i)
    {
        a.c[i]<<=1;
        a.c[i]+=t;
        t=a.c[i]/10;
        a.c[i]%=10;
    }
    if(t)
    {
        a.c[a.l++]=t;
        t=0;
    }
}
void sub(Str &a,Str &b)
{
        for(int i=0;i<a.l;++i)
        {
            if(a.c[i]>=b.c[i])
            a.c[i]-=b.c[i];
            else
            {
                a.c[i+1]--;
                a.c[i]=a.c[i]+10-b.c[i];
            }
        }
        while(a.c[a.l-1]==0)
        a.l--;
}
void show(Str &a)
{
    for(int i=0;i<a.l;++i)
        cout<<a.c[i]<<' ';
    cout<<endl;
}
int main()
{
  //  freopen("1.txt","r",stdin);
    int la,lb;
    scanf("%s%s",ar,br);
    la=strlen(ar),lb=strlen(br);
    int ia=0,sum=0;
    for(int i=la-1;i>=0;--i)
    a.c[ia++]=ar[i]-'0';
    ia=0;
    for(int i=lb-1;i>=0;--i)
    b.c[ia++]=br[i]-'0';
    a.l=la;b.l=lb;
    while(!equ(a,b))
    {
    if(!(a.c[0]&1)&&!(b.c[0]&1))
    {
    sum++;
    div(a);
    div(b);
    }
    else if(!(a.c[0]&1))
    div(a);
    else if(!(b.c[0]&1))
    div(b);
    else if(com(a,b))
    sub(a,b);
    else
    sub(b,a);
    }
    while(sum--)
        mul(a);
    ia=0;
    for(int i=a.l-1;i>=0;--i)
    ar[ia++]=a.c[i]+'0';
    ar[ia++]='\0';
    printf("%s\n",ar);
    return 0;
}

 

### 算法概述 P2152 [SDOI2009] SuperGCD 是一道要求实现高效计算两个大整数最大公约数(GCD)的题目。传统的欧几里得算法在处理大整数时由于模运算的效率问题可能表现不佳,因此需要使用更高效的算法。Stein算法(又称二进制GCD算法)是一种替代方案,它仅使用位移、加减法,避免了模运算,从而在某些场景下提高了性能。 ### Stein算法的核心思想 1. **基本性质**: - $ \text{gcd}(a, a) = a $,即一个数与其自身的最大公约数是其本身。 - $ \text{gcd}(ka, kb) = k \cdot \text{gcd}(a, b) $,即最大公约数运算与倍乘运算可以交换。 - 当 $ k $ 与 $ b $ 互质时,$ \text{gcd}(ka, b) = \text{gcd}(a, b) $,即可以移除两个数中仅一个含有的因子而不影响结果。 2. **算法步骤**: - 如果两个数都是偶数,则最大公约数一定包含因子2,因此可以同时除以2。 - 如果一个数是偶数,另一个是奇数,则偶数的因子2不影响最大公约数,可以将其除以2。 - 如果两个数都是奇数,则使用更相减损术,即用较大数减去较小数,然后继续处理,直到其中一个数为0。 3. **终止条件**: - 如果其中一个数为0,则另一个数即为最大公约数。 - 如果两个数相等,则该数即为最大公约数。 ### Python实现 以下是一个基于上述思想的Python实现,适用于处理非常大的整数: ```python def super_gcd(a, b): if a == 0: return b if b == 0: return a shift = 0 while ((a | b) & 1) == 0: # 检查a和b是否都为偶数 a >>= 1 b >>= 1 shift += 1 while (a & 1) == 0: # 如果a是偶数,将其除以2 a >>= 1 while b != 0: while (b & 1) == 0: # 如果b是偶数,将其除以2 b >>= 1 if a > b: a, b = b, a b -= a return a << shift # 最后将结果乘以2^shift # 示例输入 a = int(input()) b = int(input()) print(super_gcd(a, b)) ``` ### 相关问题 1. 如何在C++中实现Stein算法来计算两个大整数的最大公约数? 2. 在P2152题中,为什么传统的欧几里得算法在处理大整数时效率较低? 3. 如何优化Python中的大整数最大公约数计算以满足竞赛时间限制? 4. Stein算法在哪些情况下优于欧几里得算法? 5. 如何在Python中高效处理非常大的整数进行模运算和位运算?
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值