Sicily 1732 Alice and Bob(バイナリ数の最大公約数)


リンク: http://soj.me/1732
1 secs、Memory Limit:32 MB Description:Alice is a beautiful and clever girl.Bob would like to PlayAlice.One day、Alice got a very bigrectanggggggggggggggleand wantd to to divide didididididididididididididididididididededeitititinininininininininininininininininininininininininininininininininininininineeeeeeeedededededededededededededededededessssssususususususususususuスクウェア?To Alice,it’s easury to solive the proble.However,she was very busy,so she asked Bob to help her.You know Alice is such a lovely girl and of course Bob won’t refuse he request.But Bob is not so smart and he he is especially weak in math.Sohe Alturns to to you-the progrings。そして、ボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボボth and width ofthe very big rectangle(0<L、W<2^1000).The e e may be one or several spaces between these integers.Outputt:The output of the program shououout consist of one line of output for each test case.The output of aatetest case case conthe ininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininininindededededededededede100,000110 Sample Output:100
解析:本題の大意は2つの数のバイナリを与えて、彼らの最大公約数を求めて、転々相を使って除算します。本題のデータ範囲が大きいので、高精度を使う必要があります。もし簡単なカバーは転々相除法gcd(n,m)=gcd(m,n%m)を使って求めれば、高い精度の除算のプログラムを完成します。本題の入力と出力は二進法で表していますので、最大公約数は下記の方法で求められます。本題のアルゴリズムは以下の通りです。if a=2 p,b=2 q,then gcd(a,b)=2***gcd(p,q);if a=2 p,b=2 q+1,then gcd(a,b)=gcd(p,b)if a=2 p+1,b=2 q,then gcd(a,b)=gcd(a,q);if a=2 p+1,b=2 q+1,then gcd(a,b)=gcd(a-b,b)(asume a>b)前の3つの場合はいずれも一つの整数が半減してしまいます。このように減少する速度は速いです。また、入力はバイナリで入力するので、a,bを判断するのは簡単です。第四の状況を連続的に呼び出しますか?答えはできません。理由はa=2 p+1、b=2 q+1の場合:gcd(a,b)=gcd(a-b,b)=gcd(2(p-q)、2 q+1)=gcd(p-q,2 q+1);明らかに4つ目の呼び出しが連続することは不可能であり、時間の複雑さも標準的な回転位相除算と同じO(logn)である。
コードは以下の通りです
// Problem#: 1732
// Submission#: 2822044
// The source code is licensed under Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License
// All Copyright reserved by Informatic Lab of Sun Yat-sen University
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#define MAXN 10005
#define RST(N)memset(N, 0, sizeof(N))
using namespace std;

typedef struct Node_
{
    int len;
    int v[MAXN];
}Node;

Node n, m;
int cas;
char str1[MAXN], str2[MAXN];

Node Tr(char *str)     //           ;
{
    Node N;
    int len = strlen(str);
    N.len = len;
    for(int i=0; i<len; i++) N.v[i] = str[len-1-i]-'0';
    return N;
}

bool CMP(Node n, Node m)  //        ;
{
    if(n.len < m.len) return true;
    if(n.len > m.len) return false;
    for(int i=n.len-1; i>=0; i--) {
        if(n.v[i] < m.v[i]) return true;
        else if(n.v[i] > m.v[i]) return false;
    }
    return false;
}

Node Minus(Node n, Node m)   //        ,        ;
{
    Node N = n;
    int borrow = 0, temp, i;   //borrow   ;
    for(i=0; i<m.len; i++) {    //     ;
        temp = N.v[i] - borrow - m.v[i];
        if(temp >= 0) {      //    ;
            borrow = 0, N.v[i] = temp;
        }else {
            borrow = 1, N.v[i] = temp + 2;
        }
    }
    for(; i<n.len; i++) {   //      ;(  n > m)
        temp = N.v[i] - borrow;
        if(temp >= 0) {
            borrow = 0, N.v[i] = temp;
        }else {
            borrow = 1, N.v[i] = temp + 2;
        }
    }
    while(N.len >= 1 && !N.v[N.len-1]) N.len--;
    return N;
}

Node div(Node n)  //    2;      ,       ;
{
    Node ret;
    ret.len = n.len-1;
    for(int i=0; i<ret.len; i++) ret.v[i] = n.v[i+1];
    return ret;
}

void gcd(Node n, Node m)   //        ;
{
    long cnt = 0;
    while(n.len && m.len) {
        if(n.v[0]) {
            if(m.v[0]) {   //a = 2p+1, b = 2q+1   
                if(CMP(n, m)) m = Minus(m, n);
                else n = Minus(n, m);
            }else m = div(m);   //a = 2p+1, b = 2q  ;
        }else {
            if(m.v[0]) n = div(n);   //a = 2p, b = 2q+1  ;
            else {
                n = div(n), m = div(m);   //a = 2p, b = 2q  ;
                cnt++;
            }
        }
    }
    if(m.len) for(int i=m.len-1; i>=0; i--) printf("%d", m.v[i]);   //    ;
    else for(int i=n.len-1; i>=0; i--) printf("%d", n.v[i]);
    while(cnt--) printf("0");
    printf("
"); } int main() { scanf("%d", &cas); while(cas--) { scanf("%s %s", str1, str2); n = Tr(str1), m = Tr(str2); gcd(n, m); } return 0; }