Em viết chương trình thực hiện tính tổng hai phân số a/b + c/d. Với 1 ≤ a, b, c, d ≤ 1010). Lưu ý: Các phân số luôn xác định và kết quả viết dưới dạng rút gọn. Dữ liệu nhập:gồm nhiều dòng, mỗi dòng là bốn số nguyên theo thứ tự là a, b, c, d. Kết quả: In ra nhiều dòng, mỗi dòng là tổng của 2 phân số. Pascal

1 câu trả lời

// Mình dùng bignum vì sợ nếu chỉ cần 2 số tầm 10^10 thì 

// nó sẽ không bị runtime error (exit code)

uses crt;
type bignum = string;
var a, b, c, d:int64;
    tmp:bignum;
    x, y:bignum;

function cmp(a, b:bignum):boolean;
begin
    if a = b then exit(true);
    if length(a) = length(b) then
        exit(a > b);
    exit(length(a) >= length(b));
end;

function add(a, b:bignum):bignum;
var ans:bignum;
    rem, i, tmp:longint;
begin
    rem:=0; ans:='';
    while length(a) < length(b) do a:='0' + a;
    while length(b) < length(a) do b:='0' + b;
    for i:=length(a) downto 1 do
        begin
            tmp:=ord(a[i]) + ord(b[i]) - 96 + rem;
            rem:=tmp div 10;
            tmp:=tmp mod 10;
            ans:=chr(tmp + 48) + ans;
        end;
    if rem = 1 then ans:='1' + ans;
    exit(ans);
end;

function sub(a, b:bignum):bignum;
var c:bignum;
    s, br, i:longint;
begin
    br:=0; c:='';
    while length(a) < length(b) do a:='0' + a;
    while length(a) > length(b) do b:='0' + b;
    for i:=length(a) downto 1 do
        begin
            s:=ord(a[i]) - ord(b[i]) - br;
            if s < 0 then
                begin
                    s:=s + 10;
                    br:=1;
                end
            else br:=0;
            c:=chr(s + 48) + c;
        end;
    while (c[1] = '0') and (length(c) > 1) do delete(c, 1, 1);
    exit(c);
end;

function mul(a, b:int64):bignum;
var res:array[0..20] of int64;
    s:bignum;
    cnt, i:byte;
begin
    for i:=0 to 20 do res[i]:=0;
    cnt:=20; s:='';
    
    while a <> 0 do
        begin   
            inc(res[cnt], (a mod 10) * b);
            a:=a div 10;
            dec(cnt);
        end;
    for i:=20 downto 1 do 
        begin
            inc(res[i - 1], res[i] div 10);
            res[i]:=res[i] mod 10;
        end;
    for i:=1 to 20 do
        s:=s + chr(res[i] + 48);
    while (s[1] = '0') and (length(s) > 1) do delete(s, 1, 1);
    exit(s);
end;

function divmod(a, b:bignum; mode: byte):bignum;
var kb:array[0..11] of bignum;
    c, hold:bignum;
    i, k:longint;
begin
    kb[0]:='0';
    for i:=1 to 11 do
        kb[i]:=add(kb[i - 1], b);
        
    hold:=''; c:='';
    for i:=1 to length(a) do
        begin
            hold:=hold + a[i];
            k:=1;
            while cmp(hold, kb[k]) do inc(k);
            c:=c+chr(k - 1 + 48);
            hold:=sub(hold, kb[k - 1]);
            if hold[1] = '0' then delete(hold, 1, 1);
        end;
    if length(hold) = 0 then hold:='0';
    if mode = 2 then exit(hold);
    while (c[1] = '0') and (length(c) > 1) do delete(c, 1, 1);
    exit(c);
end;

function gcd(a, b:bignum):bignum;
var tmp:bignum;
begin
    while b <> '0' do
        begin
            tmp:=b;
            b:=divmod(a, b, 2);
            a:=tmp;
        end;
    exit(a);
end;
    
begin
    clrscr;

    while not eof do
        begin
            readln(a, b, c, d);
            x:=add(mul(a, d), mul(b, c));
            y:=mul(b, d);
            tmp:=gcd(x, y);
            writeln(divmod(x, tmp, 1), '/', divmod(y, tmp, 1));
        end;

end.