• bzoj1876-更相减损术


    题目描述

    Sheng bill有着惊人的心算能力,甚至能用大脑计算出两个巨大的数的GCD(最大公约 数)!因此他经常和别人比
    赛计算GCD。有一天Sheng bill很嚣张地找到了你,并要求和你比 赛,但是输给Sheng bill岂不是很丢脸!所以你
    决定写一个程序来教训他。

    输入

    共两行: 第一行:一个数A。 第二行:一个数B。
    0 < A , B ≤ 10 ^ 10000。

    输出

    一行,表示A和B的最大公约数。

    样例输入

    12
    54

    样例输出

    6
     
    这道题显然不能用欧几里得来做(高精度取模,乘,除)
    根据数学Ⅲ,我们知道了更相损减术的做法

    原文:可半者半之,不可半者,副置分母、子之数,以少减多,更相减损,求其等也。以等数约之。

    操作:

    1. 任意给定两个正整数;判断它们是否都是偶数。若是,则用2约简;若不是则执行第二步。
    2. 以较大的数减较小的数,接着把所得的差与较小的数比较,并以大数减小数。继续这个操作,直到所得的减数和差相等为止。

    优化:

      在每次减好之后都对能除2的除2,若2个都能除2,同除2,gcd*2,(我也不知道为什么会快,但数据跑出来就是这样,(求教~~~))

    //转自XT大佬

    放一个基础代码

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    int GX_gcd(int a,int b)
    {
        int tot,tt;
        if(b==0||a==0) return max(a,b);
        for(tot=0;a%2==0&&b%2==0;tot++,a/=2,b/=2);
        if(a%2==0) a/=2;
        else if(b%2==0) b/=2;
        if(a>b) tt=GX_gcd(a-b,b);else tt=GX_gcd(a,b-a);
        for(int i=1;i<=tot;i++)
        tt=tt*2;
        return tt;
    }
    int main()
    {
        int n,m;
          scanf("%d %d",&n,&m);
        cout<<GX_gcd(n,m)<<endl;        
    }

    这个不是高精度的

    高精度且非递归见下

    while(1)
        {
            if((a.nu[1]%2==0)&&(b.nu[1]%2==0)){a.div2();b.div2();num++;}
            else if((a.nu[1]%2==0)) a.div2();
            else if((b.nu[1]%2==0)) b.div2();
            if(a>b){a=a-b; if(a.z()){while(num--)b.mul2();b.out();break;}}
            else {b=b-a; if(b.z()){while(num--)a.mul2();a.out();break;}}
        }

    这里采用了位压的手段,a.nu[x]表示a上的第x个块的数字
    放一个hzw大神的代码

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #define inf 1000000000
      5 using namespace std;
      6 char ch1[10005],ch2[10005];
      7 int la,lb,cnt;
      8 struct data{int a[1205],l;}a,b;
      9 bool com()
     10 {
     11     if(a.l<b.l)return 0;
     12     if(a.l>b.l)return 1;
     13     for(int i=a.l;i>0;--i)
     14         if(a.a[i]>b.a[i])return 1;
     15         else if(a.a[i]<b.a[i])return 0;
     16     return 1;
     17 }
     18 void print(data a)
     19 {
     20     while(a.a[a.l]==0)a.l--;
     21     for(int i=a.l;i>0;--i)
     22         if(i==a.l)printf("%d",a.a[i]);
     23         else printf("%09d",a.a[i]);
     24 }
     25 inline data sub(data a,data b)
     26 {
     27     int k;
     28     data c;
     29     for(int i=1;i<=1200;++i)
     30     {
     31        if(i<=b.l)c.a[i]=a.a[i]-b.a[i];
     32        else if(i<=a.l)c.a[i]=a.a[i];
     33        else c.a[i]=0;
     34        if(c.a[i]<0)
     35        {
     36           c.a[i]+=inf;
     37           a.a[i+1]--;
     38        }
     39     }
     40     c.l=a.l;
     41     while(c.a[c.l]==0&&c.l)c.l--;
     42     return c;
     43 }
     44 void diva()
     45 {
     46     for(int i=1;i<=a.l;i++)
     47     {
     48         if(a.a[i]&1)a.a[i-1]+=inf/2;
     49         a.a[i]>>=1;
     50     }
     51     if(!a.a[a.l])a.l--;
     52 }
     53 void divb()
     54 {
     55     for(int i=1;i<=b.l;i++)
     56     {
     57         if(b.a[i]&1)b.a[i-1]+=inf/2;
     58         b.a[i]>>=1;
     59     }
     60     if(!b.a[b.l])b.l--;
     61 }
     62 void mul()
     63 {
     64     for(int i=a.l;i>0;i--)
     65     {
     66        a.a[i]<<=1;
     67        a.a[i+1]+=a.a[i]/inf;
     68        a.a[i]%=inf;
     69     }
     70     while(a.a[a.l]>0)a.l++;
     71     for(int i=b.l;i>0;i--)
     72     {
     73        b.a[i]<<=1;
     74        b.a[i+1]+=b.a[i]/inf;
     75        b.a[i]%=inf;
     76     }
     77     while(b.a[b.l]>0)b.l++;
     78 }
     79 int main()
     80 {
     81     scanf("%s%s",ch1+1,ch2+1);
     82     la=strlen(ch1+1);lb=strlen(ch2+1);
     83     if(la%9)a.l=la/9+1;
     84     else a.l=la/9;
     85     if(lb%9)b.l=lb/9+1;
     86     else b.l=lb/9;
     87     for(int i=1;i<=a.l;++i)
     88     {
     89         int k1=max(1,la-i*9+1),k2=la-(i-1)*9;
     90         for(int j=k1;j<=k2;++j)
     91             a.a[i]=a.a[i]*10+ch1[j]-'0';
     92     }
     93     for(int i=1;i<=b.l;++i)
     94     {
     95         int k1=max(1,lb-i*9+1),k2=lb-(i-1)*9;
     96         for(int j=k1;j<=k2;++j)
     97             b.a[i]=b.a[i]*10+ch2[j]-'0';
     98     }
     99     while(1)
    100     {
    101         if((a.a[1]%2==0)&&(b.a[1]%2==0)){diva();divb();cnt++;}
    102         else if((a.a[1]%2==0))diva();
    103         else if((b.a[1]%2==0))divb();
    104         if(com()){a=sub(a,b);if(!a.l){while(cnt--)mul();print(b);break;}}
    105         else {b=sub(b,a);if(!b.l){while(cnt--)mul();print(a);break;}}
    106     }
    107     //system("pause");
    108     return 0;
    109 }

    其中对于压位后前导0的输出有很大的问题(压九位)
    这里用了printf的神奇功能:printf("%09d",i);即可!

    神奇的c++!

     
     
     
     
     
     
     
     
     
     
  • 相关阅读:
    处理接口返回script标签对
    跨域问题总结
    CordMirror 在线代码编辑器
    解决IOS移动端 new Date 为 Invalid Date bug
    大屏数据可视化
    Xcode清理缓存
    ArrayMap和HashMap区别
    javacript总结
    css总结
    html总结
  • 原文地址:https://www.cnblogs.com/dancer16/p/6820414.html
Copyright © 2020-2023  润新知