数学:更相减损术

利用更相减损术求两个大数的最大公约数

这个题我没有过。。BZOJ1876

原因有这么几个:

如果使用十进制高精度配合普通更相减损术之后会T4个点

如果使用十进制高精度配合优化之后的更相减损术会T7个点

如果使用万进制高精度配合普通更相减损术会全T

最后一种不用再试了

原因我分析了一下,封装之后的十进制高精度对优化的支持不是特别好,可能要写底层操作

万进制高精度的板子玩不来

所以这道题,只给出更相减损术的普通写法和优化写法,代码不放了

等以后万进制高精度学会了再复刷此题

bign gcd1(bign m,bign n)
{
    if(m==n) return m;
    if(m>n) return gcd1(n,m-n);
    return gcd1(m,n-m);
}

这是最简单的递归形式的,但是有个缺点,不断的传参复制复制复制,然后就会MLE的

而且递归也没办法传引用

所以立刻改成了非递归形式

bign gcd2(bign &m,bign &n)
{
    bign t;
    while(!(m==n))
    {
        if(m>n)
        {
            t=m;
            m=n;
            n=t-n;
        }
        else
        {
            n=n-m;
        }
    }
    return m;
}

改的还是很合理的,效率也不错

然后咱们学习一下优化算法:

如果两个数都是偶数,那么他们一定有2这个质因子,提取2直到两个数有一个是奇数 
一奇一偶的话,提取那个偶数的2直到它变成奇数,因为奇数和它的公因子不可能是2 
然后就是两个奇数的情况,用一个减另一个,就变成了一奇一偶的情况,然后处理方法同上 
最后是剩下一个数和0,将剩下的这个数乘上一开始两个数一起提取的2,就是答案 

实现的话,我找了一分,可能找的这份效率不是特别好,但是正确性有保证,其实现思路和算法描述的一致:

bign gcd(bign &x,bign &y)
{
    int g=0;
    bign zero=0;
    bool x1,y1;
    while(!(x==zero)&&!(y==zero))
    {
        x1=!((x.s[0])&1),y1=!((y.s[0])&1);
        if(x1&&y1) {g++;x=x/2;y=y/2;}
        else if(x1||y1)
        {
            if(x1) x=x/2;
            else y=y/2;
        }
        else if (y<x) x=x-y;
        else y=y-x;
    }
    if(x<y) x=y;
    while(g--) x=x*2;
    return x;
}

不过还是跪了,这个题确实需要返工了

原文地址:https://www.cnblogs.com/aininot260/p/9479732.html