【SDOI2009】SuperGCD

【题目链接】

           点击打开链接

【算法】

          1.关于求最大公约数的算法

          若使用辗转相除法,那么显然会超时

          不妨这样思考 :

          要求gcd(a,b),

          若a为偶数,b为偶数,则gcd(a,b) = 2 * gcd(a/2,b/2)

          若a为偶数,b为奇数,则gcd(a,b) = gcd(a/2,b)

          若a为奇数,b为偶数,则gcd(a,b) = gcd(a,b/2)

          若a为奇数,b为奇数,则gcd(a,b) = gcd(b,a-b)

          这个算法的时间复杂度是log级别的

          2.高精度计算

          由于a,b<=10^100,所以要用高精度

          如果每一位存一个数会超时,所以我们每一位可以多位,例如9位,这样既省时间又省空间

【代码】

         

#include<bits/stdc++.h>
using namespace std;
#define MAXN 10000
#define MAXL 1250
const int BASE = 1e9;
 
struct INT { 
        int len;
        int num[MAXL+10]; 
} A,B,ans;
int i,n;

inline bool odd(INT x) { 
        int sta=0;
        while (!x.num[sta]) sta++;
        return x.num[sta+x.len-1] % 2;    
}

inline bool zero(INT x) {
        int i;
        for (i = 0; i <= MAXL; i++) {
                if (x.num[i] != 0)
                        return false;
        }    
        return true;
}

inline void read(INT &x) {
        int i,l,s;
        char ch[MAXN];
        scanf("%s",ch);
        x.len = 0;
        l = strlen(ch);
        for (i = 0; i < l % 9; i++) x.num[0] = (x.num[0] << 3) + (x.num[0] << 1) + ch[i] - '0';
        if (l % 9 != 0) x.len = 1;
        s = 1;
        for (i = l % 9; i < l; i++) {
                if (s == 10) { x.len++; s = 1; }
                x.num[x.len] = (x.num[x.len] << 3) + (x.num[x.len] << 1) + ch[i] - '0';
                s++;
        } 
        x.len++;
}

inline void print(INT x) {
        int i,sta=0;
        while (!x.num[sta]) sta++;
        printf("%d",x.num[sta]);
        for (i = sta + 1; i < sta + x.len; i++) printf("%09d",x.num[i]);
        puts("");    
}

INT operator -= (INT &a,INT b) {
        int i,sta1=0,sta2=0;
        static INT res;
        res.len = 0;
        memset(res.num,0,sizeof(res.num));
        while (!a.num[sta1]) sta1++;
        while (!b.num[sta2]) sta2++;
        reverse(a.num,a.num+sta1+a.len);
        reverse(b.num,b.num+sta2+b.len);
        for (i = 0; i < max(a.len,b.len); i++) {
                if (a.num[i] < b.num[i]) {
                        a.num[i] += BASE;
                        a.num[i+1]--;
                } 
                res.num[res.len++] = a.num[i] - b.num[i];
        }
        while (res.len > 1 && res.num[res.len-1] == 0) res.len--;
        reverse(res.num,res.num+res.len);
        a = res;
}

bool operator < (INT a,INT b) {
        int i,sta1=0,sta2=0;
        if (a.len < b.len) return true;
        if (b.len < a.len) return false;
        while (!a.num[sta1]) sta1++;
        while (!b.num[sta2]) sta2++;
        for (i = 0; i < a.len; i++)    {
                if (a.num[sta1+i] < b.num[sta2+i]) return true;
                if (b.num[sta2+i] < a.num[sta1+i]) return false;
        }
        return false;
}

inline void multipy2(INT &x) {
        int i,sta=0;
        while (!x.num[sta]) sta++;
        reverse(x.num+sta,x.num+sta+x.len);
        for (i = sta; i < sta + x.len; i++) x.num[i] = x.num[i] << 1;
        for (i = sta; i < sta + x.len; i++) {
                if (x.num[i] >= BASE) {
                        x.num[i+1]++;
                        x.num[i] %= BASE;
                }
        }
        if (x.num[sta+x.len]) x.len++;
        reverse(x.num+sta,x.num+sta+x.len);
}

inline void divide2(INT &x) {
        int i,n=0,sta=0;
        static INT res;
        while (!x.num[sta]) sta++;
        for (i = sta; i < sta + x.len; i++) {
                if (x.num[i] & 1) x.num[i+1] += BASE;
                x.num[i] >>= 1;
        }
      if (!x.num[sta]) x.len--; 
}
int main() {
        
        read(A); read(B);
        if (A < B) swap(A,B);
        while (!zero(B)) {
                if (odd(A) && odd(B)) A -= B;
                else if (!odd(A) && odd(B)) divide2(A);
                else if (odd(A) && !odd(B)) divide2(B);
                else { 
                        divide2(A); 
                        divide2(B); 
                        n++; 
                }    
                if (A < B) swap(A,B);
        }
        while (n--) multipy2(A);
        print(A);
        
        return 0;
    
}

 

posted @ 2018-03-18 20:47  evenbao  阅读(138)  评论(0编辑  收藏  举报