一本通1627例 3最大公约数

Posted gaojunonly1

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一本通1627例 3最大公约数相关的知识,希望对你有一定的参考价值。

1627:【例 3】最大公约数

时间限制: 1000 ms         内存限制: 524288 KB

【题目描述】

给出两个正整数 A,B,求它们的最大公约数。

【输入】

输入共两行,第一行一个正整数 A,第二行一个正整数 B。

【输出】

在第一行输出一个整数,表示 A,B 的最大公约数。

【输入样例】

18
24

【输出样例】

6

【提示】

数据范围与提示:

对于 60% 的数据,1≤A,B≤1018

对于 100% 的数据,1≤A,B≤103000 。

 

sol:Super Gcd,高精。。。

直接辗转相除肯定优秀到爆炸,所以我们选择辗转相减

然而直接辗转相减肯定也是优秀到爆炸但是这道题特别水的数据居然让我过了,这还说什么。。。

对于辗转相减有一个优化,就是对于当前两个数,如果一奇一偶,就把偶数除以2,如果两个偶,就都除以2,把答案*2,如果两奇就辗转相减。

技术图片
#include <bits/stdc++.h>
using namespace std;
typedef int ll;
inline ll read()
{
    ll s=0;
    bool f=0;
    char ch= ;
    while(!isdigit(ch))
    {
        f|=(ch==-); ch=getchar();
    }
    while(isdigit(ch))
    {
        s=(s<<3)+(s<<1)+(ch^48); ch=getchar();
    }
    return (f)?(-s):(s);
}
#define R(x) x=read()
inline void write(ll x)
{
    if(x<0)
    {
        putchar(-); x=-x;
    }
    if(x<10)
    {
        putchar(x+0);    return;
    }
    write(x/10);
    putchar((x%10)+0);
    return;
}
#define W(x) write(x),putchar(‘ ‘)
#define Wl(x) write(x),putchar(‘
‘)
inline void Read_S(char *S)
{
    
    int Len=0;
    char ch= ;
    while(!isdigit(ch))
    {
        ch=getchar();
    }
    while(ch==0)
    {
        ch=getchar();
    }
    while(isdigit(ch))
    {
        S[++Len]=ch; ch=getchar();
    }
    return;
}
const int N=3005;
const int Base=10000,Power=4;
char SX[N],SY[N];
struct BigNum
{
    int a[N];
    BigNum()
    {
        memset(a,0,sizeof a);
    }
    BigNum(char *S)
    {
        memset(a,0,sizeof a);
        int i,bb,Pos=0,Len=strlen(S+1);
        a[0]=(Len-1)/Power+1;
        for(i=1;i<=Len;i++)
        {
            if((i-1)%Power==0)
            {
                Pos++; bb=1;
            }
            a[Pos]+=bb*(S[i]-0);
            bb*=10;
        }
    }
    inline void Print()
    {
        write(a[a[0]]);
        int i;
        for(i=a[0]-1;i>=1;i--)
        {
            if(a[i]<1000) putchar(0);
            if(a[i]<100) putchar(0);
            if(a[i]<10) putchar(0);
            write(a[i]);
        }
    }
    #define P(x) x.Print(),putchar(‘ ‘)
    #define Pl(x) x.Print(),putchar(‘
‘)
}X,Y;
inline bool operator<(const BigNum &p,const BigNum &q)
{
    if(p.a[0]!=q.a[0]) return p.a[0]<q.a[0];
    int i;
    for(i=p.a[0];i>=1;i--) if(p.a[i]!=q.a[i])
    {
        return p.a[i]<q.a[i];
    }
    return false;
}
inline bool operator==(const BigNum &p,const BigNum &q)
{
    if(p.a[0]!=q.a[0]) return false;
    int i;
    for(i=p.a[0];i>=1;i--) if(p.a[i]!=q.a[i])
    {
        return false;
    }
    return true;
}
inline BigNum operator-(const BigNum &p,const BigNum &q)
{
    int i;
    BigNum ans=p;
    for(i=1;i<=q.a[0];i++)
    {
        ans.a[i]-=q.a[i];
        if(ans.a[i]<0)
        {
            ans.a[i]+=Base;
            ans.a[i+1]--;
        }
    }
    while((!ans.a[ans.a[0]])&&ans.a[0]) ans.a[0]--;
    return ans;
}
int main()
{
    freopen("data.in","r",stdin);
    freopen("my.out","w",stdout);
    Read_S(SX);
    reverse(SX+1,SX+strlen(SX+1)+1);
    X=BigNum(SX);
    Read_S(SY);
    reverse(SY+1,SY+strlen(SY+1)+1);
    Y=BigNum(SY);
    while(!(X==Y))
    {
        BigNum p,q;
        if(X<Y)
        {
            p=Y;
            q=X;
        }
        else
        {
            p=X;
            q=Y;
        }
        X=q;
        Y=p-q;
    }
    Pl(X);
    return 0;
}
意外水过的辗转相减
技术图片
#include <bits/stdc++.h>
using namespace std;
typedef int ll;
inline ll read()
{
    ll s=0;
    bool f=0;
    char ch= ;
    while(!isdigit(ch))
    {
        f|=(ch==-); ch=getchar();
    }
    while(isdigit(ch))
    {
        s=(s<<3)+(s<<1)+(ch^48); ch=getchar();
    }
    return (f)?(-s):(s);
}
#define R(x) x=read()
inline void write(ll x)
{
    if(x<0)
    {
        putchar(-); x=-x;
    }
    if(x<10)
    {
        putchar(x+0);    return;
    }
    write(x/10);
    putchar((x%10)+0);
    return;
}
#define W(x) write(x),putchar(‘ ‘)
#define Wl(x) write(x),putchar(‘
‘)
inline void Read_S(char *S)
{
    
    int Len=0;
    char ch= ;
    while(!isdigit(ch))
    {
        ch=getchar();
    }
    while(ch==0)
    {
        ch=getchar();
    }
    while(isdigit(ch))
    {
        S[++Len]=ch; ch=getchar();
    }
    return;
}
const int N=3005;
const int Base=10000,Power=4;
char SX[N],SY[N];
struct BigNum
{
    int a[N];
    BigNum()
    {
        memset(a,0,sizeof a);
    }
    BigNum(char *S)
    {
        memset(a,0,sizeof a);
        int i,bb,Pos=0,Len=strlen(S+1);
        a[0]=(Len-1)/Power+1;
        for(i=1;i<=Len;i++)
        {
            if((i-1)%Power==0)
            {
                Pos++; bb=1;
            }
            a[Pos]+=bb*(S[i]-0);
            bb*=10;
        }
    }
    inline void Print()
    {
        write(a[a[0]]);
        int i;
        for(i=a[0]-1;i>=1;i--)
        {
            if(a[i]<1000) putchar(0);
            if(a[i]<100) putchar(0);
            if(a[i]<10) putchar(0);
            write(a[i]);
        }
    }
    #define P(x) x.Print(),putchar(‘ ‘)
    #define Pl(x) x.Print(),putchar(‘
‘)
}X,Y,Ans;
inline bool operator<(const BigNum &p,const BigNum &q)
{
    if(p.a[0]!=q.a[0]) return p.a[0]<q.a[0];
    int i;
    for(i=p.a[0];i>=1;i--) if(p.a[i]!=q.a[i])
    {
        return p.a[i]<q.a[i];
    }
    return false;
}
inline bool operator==(const BigNum &p,const BigNum &q)
{
    if(p.a[0]!=q.a[0]) return false;
    int i;
    for(i=p.a[0];i>=1;i--) if(p.a[i]!=q.a[i])
    {
        return false;
    }
    return true;
}
inline BigNum operator-(const BigNum &p,const BigNum &q)
{
    int i;
    BigNum ans=p;
    for(i=1;i<=q.a[0];i++)
    {
        ans.a[i]-=q.a[i];
        if(ans.a[i]<0)
        {
            ans.a[i]+=Base;
            ans.a[i+1]--;
        }
    }
    while((!ans.a[ans.a[0]])&&ans.a[0]) ans.a[0]--;
    return ans;
}
inline BigNum operator*(const BigNum &p,const BigNum &q)
{
    int i,j;
    BigNum ans; ans.a[0]=max(p.a[0],q.a[0]);
    for(i=1;i<=p.a[0];i++)
    {
        for(j=1;j<=q.a[0];j++)
        {
            ans.a[i+j-1]+=p.a[i]*q.a[j];
            ans.a[i+j]+=ans.a[i+j-1]/Base;
            ans.a[i+j-1]%=Base;
        }
    }
    while(ans.a[ans.a[0]+1]) ans.a[0]++;
    while(!ans.a[ans.a[0]]) ans.a[0]--;
    return ans;
}
inline bool Judge_Ou(BigNum p)
{
    if(!p.a[0]) return 1;
    return (p.a[1]&1)?0:1;
}
inline BigNum Div2(BigNum p)
{
    BigNum ans;
    ans.a[0]=p.a[0];
    int i;
    for(i=p.a[0];i>=1;i--)
    {
        ans.a[i]+=(p.a[i]>>1);
        if(p.a[i]&1) p.a[i-1]+=Base;
    }
    while(!ans.a[ans.a[0]]) ans.a[0]--;
    return ans;
}
inline BigNum Mul2(BigNum p)
{
    BigNum ans;
    ans.a[0]=p.a[0];
    int i;
    for(i=1;i<=p.a[0];i++)
    {
        p.a[i]<<=1;
        if(p.a[i]>Base)
        {
            ans.a[i+1]+=p.a[i]/Base;
            p.a[i]%=Base;
        }
        ans.a[i]+=p.a[i];
    }
    while(ans.a[ans.a[0]+1]) ans.a[0]++;
    return ans;
}
int main()
{
    freopen("data.in","r",stdin);
    freopen("my.out","w",stdout);
    Read_S(SX);
    reverse(SX+1,SX+strlen(SX+1)+1);
    X=BigNum(SX);
    Read_S(SY);
    reverse(SY+1,SY+strlen(SY+1)+1);
    Y=BigNum(SY);
    Ans.a[0]=Ans.a[1]=1;
    while(!(X==Y))
    {
//        P(X); Pl(Y);
        bool BoX=Judge_Ou(X),BoY=Judge_Ou(Y);
        if(BoX)
        {
            if(BoY)
            {
                X=Div2(X); Y=Div2(Y); Ans=Mul2(Ans);
            }
            else
            {
                X=Div2(X);
            }
        }
        else
        {
            if(BoY)
            {
                Y=Div2(Y);
            }
            else
            {
                BigNum p,q;    
                if(X<Y) p=Y,q=X;
                else p=X,q=Y;
                X=p-q; Y=q;
            }
        }
    }
    Ans=Ans*X;
    Pl(Ans);
    return 0;
}
带优化的正确姿势

 

以上是关于一本通1627例 3最大公约数的主要内容,如果未能解决你的问题,请参考以下文章

一本通 1275:例9.19乘积最大

一本通1626例 2Hankson 的趣味题

算法?日更?第十七期信息奥赛一本通1598: 例 2最大连续和题解

#10178. 「一本通 5.5 例 4」旅行问题

#10064 「一本通 3.1 例 1」黑暗城堡

「一本通 6.2 例 1」Prime Distance