kết quả từ 1 tới 4 trên 4

bài tập phép nhân...khó quá mọi người giúp đỡ

  1. #1
    Ðến Từ
    Quảng Bình
    Thành Viên Thứ: 377431
    Giới tính: Nam
    Bài gửi
    16

    bài tập phép nhân...khó quá mọi người giúp đỡ

    HTML Code:
    Cho hai số nguyên dương n,m có x, y chữ số ( 1<= x,y < 10000 ) 
    yêu cầu tính tích của hai số n,m 
    Dữ liệu vào
        dòng 1: ghi hai số x,y là  số lượng chữ số của  n,m, hai số cách nhau một dấu cách
       dòng 2: ghi số nguyên n,
        Dòng 3: ghi số nguyên m 
    dữ liệu ra 
        dòng 1: ghi số lượng chữ số của tích n,m
        dòng 2: ghi kết quả của phép nhân
    VD TICH.IN           PTICH.OUT
    5 3                          7
    24586
    123                       3024078
    ai giúp mình cho xin cai code xử lí bài này với ak...
    Quick reply to this message Trả lời       

  2. #2
    Ðến Từ
    TP. Hồ Chí Minh
    Thành Viên Thứ: 56897
    Giới tính: Nam
    Bài gửi
    881

    Reply: bài tập phép nhân...khó quá mọi người giúp đỡ

    Bài này kỹ thuật lập trính thôi chứ không khó đâu.
    - Đầu tiên về lưu trữ số thì bạn có 2 lựa chọn: dùng mảng của longint hoặc dùng ansistring để lưu. Mình khuyến khích bạn nên lưu số ngược, tức là hàng đơn vị ở index 1 trong mảng.
    - Bạn cần 2 functions sau: cộng 2 số và nhân 1 số với 1 chữ số. Bạn thực hiện phép toán bằng tay thế nào thì viết cho chạy như vậy.
    - Sau đó function nhân 2 số thì tổng hợp của 2 functions kia lại.

    Ví dụ về cộng 2 số dùng chuỗi (assume chuỗi a và b đc lưu ngược nhé):
    Mã:
    function sum(a, b : ansistring; offset : integer) : ansistring;
    var i, carry, k, xa, xb, t : integer;
        c : ansistring;
    begin
        c := '';
        carry := 0;
        k := max(length(a), length(b) + offset);
        for i := 1 to k do
            begin
                xa := 0;
                if (i <= length(a)) then
                    xa := ord(a[i]) - 48;
                xb := 0;
                if (offset < i) and (i <= length(b) + offset) then
                    xb := ord(b[i - offset]) - 48;
                t := xa + xb + carry;
                carry := t div 10;
                c := c + chr(t mod 10 + 48);
            end;
        if (carry > 0) then
            c := c + '1';
        exit(c);
    end;


    Tốc độ: Nếu bạn muốn nhanh thì bạn nên dùng mảng của longint VÀ lưu theo hệ cơ số 10^4, đương nhiên sẽ khó viết hơn một tí.
    LCD: 13.3" 1920x1080 IPS
    CPU: Intel i7 - 4700MQ (2.4 GHz - 3.4 GHz)
    GPU: Nvidia GTX 765m with GDDR5 2GB
    RAM: 2x8GB G.Skill 2133
    HDD: Samsung SSD 850 Pro 512 GB
    2 kg.

  3. Đã cảm ơn tengiday:


  4. #3
    Ðến Từ
    Quảng Bình
    Thành Viên Thứ: 377431
    Giới tính: Nam
    Bài gửi
    16

    Reply: bài tập phép nhân...khó quá mọi người giúp đỡ

    hiện tại mình đang chạy trên tp 7.0 nên mình chọn cách lưu trữ bằng mảng.chỗ này mình biết nhưng bạn có thể chỉ rõ hai ham ròi kết hợp tạo thành bài này được ko ak

  5. #4
    Ðến Từ
    TP. Hồ Chí Minh
    Thành Viên Thứ: 56897
    Giới tính: Nam
    Bài gửi
    881

    Reply: bài tập phép nhân...khó quá mọi người giúp đỡ

    Để đơn giản thì bạn lưu thế này. Ví dụ số 843 sẽ đc lưu trong mảng a là:
    Mã:
    Index i 1 2 3
    a[i] 3 4 8
    Còn cần 1 biến na = 3 để lưu trữ số chữ số của a.
    Về phép cộng và nhân thì bạn làm tay thế nào thì viết cho nó chạy y như thế. Mình không có Pascal nên chỉ code nhanh thế này thôi nhé.
    Mã:
    uses math;
    type number = array[1..20001] of integer;
    var a, b, c : number;
        na, nb, nc : integer;
    
    // in ra số 'a'. Số 'a' có 'na' chữ số.
    procedure printNumber(a : number; na : integer);
    var i : integer;
    begin
        for i := na downto 1 do
            write(a[i]);
        writeln;
    end;
    
    // tính tổng của 2 số 'a' và 'b', với 'b' đc dịch sang bên trái 'offset' chữ số.
    // kết quả đc lưu vào số 'a'.
    procedure sum(var a, b : number; var na : integer; nb, offset : integer);
    var i, carry, k, xa, xb, nrs : integer;
    begin
        k := max(na, nb + offset);
        carry := 0;
        nrs := 0;
        for i := 1 to k do
            begin
                xa := 0;
                if (i <= na) then
                    xa := a[i];
                xb := 0;
                if (offset < i) and (i <= nb + offset) then
                    xb := b[i - offset];
                inc(nrs);
                a[nrs] := xa + xb + carry;
                carry := a[nrs] div 10;
                a[nrs] := a[nrs] mod 10;
            end;
        if (carry > 0) then
            begin
                inc(nrs);
                a[nrs] := 1;
            end;
        na := nrs;
    end;
    
    // nhân số 'a' với 1 chữ số 'digit'. Kết quá đc lưu ở 'c' với 'nc' chữ số.
    procedure multiply_digit(a : number; na, digit : integer; var c : number; var nc : integer);
    var i, carry : integer;
    begin
        nc := 0;
        carry := 0;
        for i := 1 to na do
            begin
                inc(nc);
                c[nc] := a[i] * digit + carry;
                carry := c[nc] div 10;
                c[nc] := c[nc] mod 10;
            end;
        if (carry > 0) then
            begin
                inc(nc);
                c[nc] := carry;
            end;
    end;
    
    // nhân 2 số lớn 'a' và 'b'. Kết quả đc lưu ở 'c' với 'nc' chữ số.
    procedure multiply(a, b : number; na, nb : integer; var c : number; var nc : integer);
    var i, nd : integer;
        d : number;
    begin
        multiply_digit(a, na, b[1], c, nc);
        for i := 2 to nb do
            begin
                multiply_digit(a, na, b[i], d, nd);
                sum(c, d, nc, nd, i - 1);
            end;
    end;
    
    BEGIN
        a[1] := 3; a[2] := 4; a[3] := 8; na := 3; // 843
        b[1] := 7; b[2] := 0; b[3] := 9; b[4] := 1; nb := 4; // 1907
        
        multiply(a, b, na, nb, c, nc);
        printNumber(c, nc);
        
    END.

    Mình nghĩ 2 số 10^4 chữ số thì sẽ mất ít nhất cũng 5 giây. Nếu dùng hệ cơ số 10^4 thì ct sẽ chạy nhanh hơn, nhưng khó viết hơn.

  6. Đã cảm ơn tengiday: