链接:http://acm.ocrosoft.com/problem.php?cid=1702&pid=0

题目描述

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

输入

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

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

输出

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

样例输入

18

24

样例输出

6

思路:

这道题是一道大数的约数题,用普通的辗转相除法肯定会TLE因此我们要用大数的转转相除法

代码:

#include<iostream>

#include<cstdio>

#include<cstring>

#define inf 1000000000

using namespace std;

char ch1[10005],ch2[10005];

int la,lb,cnt;

struct data{

int a[1205],l;

}a,b;//建立结构体,a数组存数字,l表示长度

bool com()//比较函数,比较两个数大小

{

    if(a.l<b.l)

return 0;

    if(a.l>b.l)

return 1;

    for(int i=a.l;i>0;--i)

        if(a.a[i]>b.a[i])

return 1;

        else if(a.a[i]<b.a[i])

return 0;

    return 1;

}

void print(data a)//输出函数

{

    while(a.a[a.l]==0)

a.l--;

    for(int i=a.l;i>0;--i)

        if(i==a.l)

printf("%d",a.a[i]);

        else printf("%09d",a.a[i]);

}

inline data sub(data a,data b)//高精度辗转相除法

{

    int k;

    data c;//用于记录中间值,以及最后输出结果

    for(int i=1;i<=1200;++i)

    {

       if(i<=b.l)

   c.a[i]=a.a[i]-b.a[i];

       else if(i<=a.l)

   c.a[i]=a.a[i];

       else

   c.a[i]=0;

       if(c.a[i]<0)

       {

          c.a[i]+=inf;

          a.a[i+1]--;

       }

    }

    c.l=a.l;

    while(c.a[c.l]==0&&c.l)//除去前导零

c.l--;

    return c;

}

void diva()//去2操作

{

    for(int i=1;i<=a.l;i++)

    {

        if(a.a[i]&1)a.a[i-1]+=inf/2;

        a.a[i]>>=1;

    }

    if(!a.a[a.l])

a.l--;

}

void divb()

{

    for(int i=1;i<=b.l;i++)

    {

        if(b.a[i]&1)b.a[i-1]+=inf/2;

        b.a[i]>>=1;

    }

    if(!b.a[b.l])

b.l--;

}

void mul()//重新将2加回

{

    for(int i=a.l;i>0;i--)

    {

       a.a[i]<<=1;

       a.a[i+1]+=a.a[i]/inf;

       a.a[i]%=inf;

    }

    while(a.a[a.l]>0)

a.l++;

    for(int i=b.l;i>0;i--)

    {

       b.a[i]<<=1;

       b.a[i+1]+=b.a[i]/inf;

       b.a[i]%=inf;

    }

    while(b.a[b.l]>0)

b.l++;

}

int main()

{

    scanf("%s%s",ch1+1,ch2+1);

    la=strlen(ch1+1);

lb=strlen(ch2+1);

    if(la%9)

a.l=la/9+1;//以九位为单位,分割大数

    else

a.l=la/9;

    if(lb%9)

b.l=lb/9+1;

    else

b.l=lb/9;

    for(int i=1;i<=a.l;++i)

    {

        int k1=max(1,la-i*9+1),k2=la-(i-1)*9;

        for(int j=k1;j<=k2;++j)

        a.a[i]=a.a[i]*10+ch1[j]-'0';

    }

    for(int i=1;i<=b.l;++i)

    {

        int k1=max(1,lb-i*9+1),k2=lb-(i-1)*9;

        for(int j=k1;j<=k2;++j)

        b.a[i]=b.a[i]*10+ch2[j]-'0';

    }

    while(1)

    {

        if((a.a[1]%2==0)&&(b.a[1]%2==0))

{

diva();

divb();

cnt++;

}

        else if((a.a[1]%2==0))

diva();

        else if((b.a[1]%2==0))

divb();

        if(com())

{

a=sub(a,b);

if(!a.l)

{

while(cnt--)

mul();

print(b);

break;

}

}

        else

{

b=sub(b,a);

if(!b.l)

{

while(cnt--)

mul();

print(a);

break;

}

}

    }

    return 0;