zoukankan      html  css  js  c++  java
  • bzoj1876 [SDOI2009]SuperGCD

    1876: [SDOI2009]SuperGCD

    Time Limit: 4 Sec  Memory Limit: 64 MB
    Submit: 3744  Solved: 1349
    [Submit][Status][Discuss]

    Description

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

    Input

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

    Output

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

    Sample Input

    12
    54

    Sample Output

    6

    HINT

     

    Source

    分析:这道题是一道非常烦人的高精度问题,求gcd谁都会,但是直接用欧几里得算法,高精度取模直接gg,而且还是压位的,打出来估计要半天.那么换一种方法:更相减损术:
    第一步:任意给定两个正整数;判断它们是否都是偶数。若是,则用2约简;若不是则执行第二步。
    第二步:以较大的数减较小的数,接着把所得的差与较小的数比较,并以大数减小数。继续这个操作,直到所得的减数和差相等为止。
    则第一步中约掉的若干个2与第二步中等数的乘积就是所求的最大公约数。
    其中所说的“等数”,就是最大公约数。求“等数”的办法是“更相减损”法。        ----摘自百度百科
    也就是说我们只需要设计乘法,除法和减法就可以了。高精度算法就相当于模拟我们算术一样,只不过用程序跑而已,步骤是先操作,再进位、补位,最后看数组的长度有没有改变.
    这道题一定要压位来处理,不然会tle,压位后的操作与没有压位差不多,只不过mod的数变了,以前是逢10进1,现在是逢n进1.
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    #include<cmath>
    #include<map>
    
    using namespace std;
    
    const int mod = 100000000;
    
    int tot;
    
    struct node
    {
        int x[2010], len;
    }a,b;
    
    void read(node &c)
    {
        char s[10010];
        scanf("%s", s);
        int len = strlen(s),cnt = 0,chengji = 1;
        for (int i = len - 1; i >= 0; i--)
        {
            cnt = cnt + (s[i] - '0')* chengji;
            chengji *= 10;
            if ((len - i) % 8 == 0)
            {
                c.x[++c.len] = cnt;
                cnt = 0;
                chengji = 1;
            }
        }
        if (cnt != 0)
            c.x[++c.len] = cnt;
    }
    
    void div1()
    {
        for (int i = a.len; i >= 1; i--)
        {
            if (a.x[i] % 2 == 1)
                a.x[i - 1] += mod;
            a.x[i] >>= 1;
        }
        while (a.x[a.len] == 0 && a.len > 1)
            a.len--;
    }
    
    void div2()
    {
        for (int i = b.len; i >= 1; i--)
        {
            if (b.x[i] % 2 == 1)
                b.x[i - 1] += mod;
            b.x[i] >>= 1;
        }
        while (b.x[b.len] == 0 && b.len > 1)
            b.len--;
    }
    
    bool check()
    {
        if (a.len != b.len)
            return false;
        for (int i = 1; i <= a.len; i++)
            if (a.x[i] != b.x[i])
                return false;
        return true;
    }
    
    bool cmp()
    {
        if (a.len > b.len)
            return true;
        else
            if (a.len < b.len)
                return false;
        for (int i = a.len; i >= 1; i--)
        {
            if (a.x[i] > b.x[i])
                return true;
            else
                if (a.x[i] < b.x[i])
                    return false;
        }
        return true;
    }
    
    void jian(node &c, node d)
    {
        for (int i = 1; i <= c.len; i++)
        {
            if (c.x[i] >= d.x[i])
                c.x[i] -= d.x[i];
            else
            {
                c.x[i] = c.x[i] + mod - d.x[i];
                c.x[i + 1]--;
            }
        }
        while (c.x[c.len] == 0 && c.len > 1)
            c.len--;
    }
    
    void mul()
    {
        for (int i = 1; i <= a.len; i++)
            a.x[i] <<= 1;
        for (int i = 1; i <= a.len; i++)
            if (a.x[i] >= mod)
            {
            a.x[i] -= mod;
            a.x[i + 1]++;
            }
        while (a.x[a.len + 1])
            a.len++;
    }
    
    void print()
    {
        printf("%d", a.x[a.len]);
        for (int i = a.len - 1; i >= 1; i--)
            printf("%08d", a.x[i]);
        printf("
    ");
    }
    
    int main()
    {
        read(a);
        read(b);
        while (a.x[1] % 2 == 0 && b.x[1] % 2 == 0)
        {
            tot++;
            div1();
            div2();
        }
        while (!check())
        {
            if (cmp())
                jian(a, b);
            else
                jian(b, a);
            while (a.x[1] % 2 == 0)
                div1();
            while (b.x[1] % 2 == 0)
                div2();
        }
        while (tot--)
            mul();
        print();
    
        return 0;
    }
     
  • 相关阅读:
    web中的安全编码
    网站安全(学习)
    head 命令(转)
    less 命令(转)
    简单网站优化
    Yahoo团队总结的关于网站性能优化的经验(转)
    more命令(转)
    linux安装oracle
    Ubuntu系统环境变量配置文件(转)
    nl命令(转)
  • 原文地址:https://www.cnblogs.com/zbtrs/p/7397038.html
Copyright © 2011-2022 走看看