[SDOI2009]SuperGCD

本文深入探讨了高精度最大公约数(GCD)的计算方法,提供了详细的算法步骤及其实现代码,包括如何处理偶数和奇数情况,以及通过减法和除法进行优化的策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接

这题。高精度。恶心。难受。

那么高精度的gcd怎么做呢?

若a=b gcd(a,b)=a

①a偶b偶 gcd(a,b)=2*gcd(a/2,b/2)

②a偶b奇 gcd(a,b)=gcd(a/2,b)

③a奇b奇 gcd(a,b)=gcd(a-b,b)

嗯。这玩意就这样了。

#include<cmath>
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define ll long long
using namespace std;
int a[100000],b[100000],c[100000],f[100000],s0,T,kpl[100000],kyl;
char s[100000];
void bigscanf(int *a){
    scanf("%s",s);
    int len=strlen(s),i,j;
    for(i=0;i<len;++i){
        j=(len-i+3)/4;
        a[j]=a[j]*10+s[i]-'0';
    }
    a[0]=(len+3)/4;
}                                 
void bigprintf(int *a){ 
 cout<<a[a[0]];
 for(int i=a[0]-1;i>0;--i){
     for(int j=1000;j>0;j/=10)cout<<a[i]/j%10;
    }
    cout<<endl;
}                    
int bigcmp(int *a,int *b){ 
    if(a[0]>b[0])return 1;
    if(a[0]<b[0])return -1;
    for(int i=a[0];i>0;i--){
        if(a[i]>b[i])return 1;
        if(a[i]<b[i])return -1;
    }
    return 0;
}
void bigsub(int *a,int *b){
    int k=a[0],g=0;
    for(int i=1;i<=k;i++){                       
        a[i]=a[i]-b[i];
        if(a[i]<0){
            a[i+1]--;
            a[i]=a[i]+10000;
        }
        else g=0;
    }
    while(k>0&&a[k]==0)k--;
    a[0]=k;
}
void bigmul2(int *a,int *b,int *c){
    int k=a[0]+b[0];
    for(int i=1;i<=a[0];i++){
        for(int j=1;j<=b[0];j++){
            c[i+j-1]=c[i+j-1]+a[i]*b[j];
            c[i+j]=c[i+j]+c[i+j-1]/10000;
            c[i+j-1]=c[i+j-1]%10000;
        }
    }
    while(k>0&&c[k]==0)k--;
    c[0]=k;
}
void bigmul1(int *a,int b){
    int k=a[0],g=0;
    for(int i=1;i<=a[0];i++){
        a[i]=a[i]*b+g;
        g=a[i]/10000;
        a[i]=a[i]%10000;
    }
    while(g>0){
        k++;
        a[k]=g%10000;
        g=g/10000;
    }
    while(k>0&&a[k]==0)k--;
    a[0]=k;
}
void bigdiv1(int *a,int b){
    int k=a[0],d=0;
    for(int i=a[0];i>=1;i--){
        d=d*10000+a[i];
        a[i]=d/b;
        d=d%b;
    }
    while(k>0&&a[k]==0)k--;
    a[0]=k;
}
void copy(int *a,int *b){
    for(int i=0;i<=b[0];++i){
        a[i]=b[i];
    }
}
void Gcd(int *a,int *b,int t){
    int u=bigcmp(a,b);//cout<<u<<endl;
    if(u==0){T=t;return;}
    if(u<0){Gcd(b,a,t);return;}
    int ta=0,tb=0;
    if(a[1]%2==0){
        bigdiv1(a,2);
        ta=1;
    }
    if(b[1]%2==0){
        bigdiv1(b,2);
        tb=1;
    }
    if(ta&&tb)Gcd(a,b,t+1);
    else if(! ta&&! tb){bigsub(a,b);Gcd(a,b,t);}
    else Gcd(a,b,t);
}
int main(){
    bigscanf(a);
    bigscanf(b);
    Gcd(a,b,0);
    if(T==0)bigprintf(a);
    else {
        f[0]=f[1]=1;
        for(int i=1;i<=T;i++)bigmul1(f,2);
        bigmul2(f,a,kpl);
        copy(f,kpl);
        bigprintf(f);
    }
return 0;
}

 

转载于:https://www.cnblogs.com/clockwhite/p/10658878.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值