最大公约数(信息学奥赛一本通 1627)

【题目描述】

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

【输入】

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

【输出】

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

【输入样例】

18
24

【输出样例】

6

【提示】

数据范围与提示:

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

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



 首先看到这道题的数据范围之后,我们肯定是得用高精度呐,然后为了方便一点,缩小数组大小,我们还可以引进“压位高精度”,一般来说,最好使用四位压一位,用五位的话容易爆掉...

--->关于“压位高精”,可以去看看这位大佬的博客,感jio讲的很清楚

进入正题,此题要求两个高精的“最大公约数”,那我们肯定会想到用“二进制算法”呐,

--->关于“二进制算法”,可以去看看我的另一篇博客(应该在最后面有讲到),也称“更相减损术”啦

那我直接上代码吧(反正是一道模板题...

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 const int N=1e6+5,inf=1<<29,base=10000;//10000而不是100000,不然容易爆掉! 
  4 int T;
  5 int a[1000],b[1000],c[1000],f[1000];
  6 int read()
  7 {
  8     int f=1;char ch;
  9     while((ch=getchar())<'0'||ch>'9')
 10         if(ch=='-')f=-1;
 11     int res=ch-'0';
 12     while((ch=getchar())>='0'&&ch<='9')
 13         res=res*10+ch-'0';
 14     return res*f;
 15 }
 16 void write(int x)
 17 {
 18     if(x<0)
 19     {
 20         putchar('-');
 21         x=-x;
 22     }
 23     if(x>9)write(x/10);
 24     putchar(x%10+'0');
 25 }
 26 /*int gcd(int x,int y)
 27 {
 28     if(y==0)return x;
 29     else return gcd(y,x%y);
 30 }*/
 31 //欧几里得算法~显然不行 
 32 void init(int a[])//压位高精度 
 33 {
 34     string s;
 35     cin>>s;
 36     int len=s.length(),i,j;
 37     for(i=0;i<len;i++)
 38     {
 39         j=(len-i+3)/4;//注意是len-i+3,而不是+4! 
 40         a[j]=a[j]*10+s[i]-'0';
 41     }
 42     a[0]=(len+3)/4;
 43 }
 44 int com(int a[],int b[])//比较大小 
 45 {
 46     if(a[0]>b[0])return 1;
 47     if(a[0]<b[0])return -1;
 48     for(int i=a[0];i>=1;i--)
 49     {
 50         if(a[i]>b[i])return 1;
 51         else if(a[i]<b[i])return -1;
 52     }
 53     return 0;
 54 }
 55 void div(int a[])//高精除2 
 56 {
 57     int tmp=0;
 58     for(int i=a[0];i>=1;i--)
 59     {
 60         tmp=tmp*base+a[i];
 61         a[i]=tmp/2;
 62         tmp%=2;
 63     }
 64     while(a[a[0]]==0&&a[0]>0)a[0]--;
 65 }
 66 void jian(int a[],int b[])//高精减高精 
 67 {
 68     for(int i=1;i<=a[0];i++)
 69     {
 70         a[i]-=b[i];
 71         if(a[i]<0)
 72         {
 73             a[i+1]--;
 74             a[i]+=base;
 75         }
 76         while(a[a[0]]==0&&a[0]>0)a[0]--;
 77     }
 78 }
 79 void gcd(int a[],int b[],int t)//二进制算法 
 80 {
 81     if(com(a,b)==0)//如果二者相同,那就是最大公约数无疑了 
 82     {
 83         T=t;
 84         return ;
 85     }
 86     if(com(a,b)<0)
 87     {
 88         gcd(b,a,t);
 89         return ;
 90     }
 91     int ta=0,tb=0;
 92     if(a[1]%2==0)
 93     {
 94         div(a);
 95         ta=1;
 96     }
 97     if(b[1]%2==0)
 98     {
 99         div(b);
100         tb=1;
101     }
102     if(ta&&tb)gcd(a,b,t+1);
103     else if(!ta&&!tb)
104     {
105         jian(a,b);
106         gcd(a,b,t);
107     }
108     else gcd(a,b,t);
109 }
110 void print(int a[])//高精输出 
111 {
112     write(a[a[0]]);
113     for(int i=a[0]-1;i>0;i--)//这里可是有点学问的,不能直接像输出a[a[0]]一样输出其他几位,
114         for(int j=base/10;j>0;j/=10)//因为其他几位可能最高位为0,直接输出则0被吞掉了 
115             write(a[i]/j%10);
116 }
117 void mulow(int a[],int k)//高精乘低精 
118 {
119     for(int i=1;i<=a[0];i++)a[i]*=k;
120     for(int i=1;i<=a[0];i++)
121     {
122         a[i+1]+=a[i]/base;
123         a[i]%=base;
124     }
125     while(a[a[0]+1]>0)
126     {
127         a[0]++;
128         a[a[0]+1]=a[a[0]]/base;
129         a[a[0]]%=base;
130     }
131 }
132 void mulhigh(int a[],int b[])//高精乘高精 
133 {
134     for(int i=1;i<=a[0];i++)
135         for(int j=1;j<=b[0];j++)
136         {
137             c[i+j-1]+=a[i]*b[j];
138             c[i+j]+=c[i+j-1]/base;
139             c[i+j-1]%=base;
140         }
141     c[0]=a[0]+b[0];
142     while(c[c[0]]==0&&c[0]>0)c[0]--;
143     for(int i=0;i<=c[0];i++)a[i]=c[i];    
144 }
145 int main()
146 {
147     init(a);init(b);
148     gcd(a,b,0);
149     if(T==0)print(a);//T存储最大公约数中有多少个2 
150     else 
151     {
152         f[0]=f[1]=1;
153         for(int i=1;i<=T;i++)
154             mulow(f,2);//将2累乘 
155         mulhigh(f,a);
156         print(f);
157     }
158     return 0;
159 }
View Code
原文地址:https://www.cnblogs.com/ljy-endl/p/11392740.html