zoukankan      html  css  js  c++  java
  • 最大公约数(信息学奥赛一本通 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
  • 相关阅读:
    036 Python进阶小结
    035 异常处理
    033 数据类型分类
    034 Python深浅拷贝
    032 集合类型内置方法
    031 字典类型内置方法
    XML删除节点
    追加XML
    XML文档的读、写
    XML文档的创建
  • 原文地址:https://www.cnblogs.com/ljy-endl/p/11392740.html
Copyright © 2011-2022 走看看