Trong lóc ®ã nhiÒu bµi to¸n cÇn thùc hiÖn phÐp to¸n víi hµng tr¨m, thËm chÝ hµng ngµn ch÷ sè... C¸c bµi to¸n øng dông.[r]
Trang 1Chuyên đề Các phép tính với số lớn trong NNLT Pascal
( VVSửu., GV Tr-ờng THPT chuyên HN-AMSTERDAM)
I Đặt vấn đề
Do hạn chế về bộ nhớ, nên các phép toán cộng, trừ, nhân, chia trong NNLT pascal chỉ thực hiện đ-ợc đối với các số nhỏ Trong lúc đó nhiều bài toán cần thực hiện phép toán với hàng trăm, thậm chí hàng ngàn chữ số Chúng ta sẽ
sử dụng một vài cấu trúc dữ liệu nh- xâu, mảng và các thuật toán đã học từ thời THCS để thực hiện yêu cầu tính toán đối với các số lớn
II Các bài toán cơ bản
Bài toán 1 Cộng 2 số lớn
Input: Cho S1, S2 là 2 số nguyên d-ơng, mỗi số có số chữ số <=200 (nhập d-ới dạng xâu)
Output: S1+S2
Thuật toán:
- Tạo các thủ tục :
+procedure DOI (S:string, Var a :mang);
{ đổi các kí tự số từ S thành các số t-ơng ứng trong mảng a (với thứ tự ngựợc lại)}
Var n, i, cod: integer;
Begin
n:=length(S);
For i:= n downto 1 do
Begin
val(s[i],a[n-i],cod)
End ;
+Procedure CONG (a,b: mang; var c:mang);
Var nho, tg: integer;
Begin
Nho:=0;
For i:= 0 to 300 do
Begin
Tg:=a[i]+b[i]+ nho;
c[i]:=tg mod 10;
nho:=tg div 10;
End;
End;
Trang 2+ procedure INKQ (c:mang);
Var sc,i: integer;
Begin
For sc :=300 downto 0 do if c[sc]<>0 then break; For i:=sc downto 0 do write(c[i]);
End;
Begin {main}
READLN( S1, S2);
DOI(S1,a);
DOI(S2,b);
CONG (a,b,c);
INKQ(c);
End
Bài toán 2 Hiệu 2 số lớn
Input : S1, S2 Xâu biểu diễn số (giả thiết s1≥ s2)
Output : S1- S2
Begin
Readln(S1, S2);
DOI(s1,a); DOI(s2,b);
TRU(a,b,h);
INKQ(h);
End
Procedure TRU(a,b:mang;var h:mang);
Var
Begin
Muon:=0;
For i:=0 to 300 do
Begin
b[i]:=b[i]+muon;
If a[i]>=b[i] then begin h[i]:=a[i]-b[i]; muon:=0;end Else
Begin
muon:=1;
h[i]:=10+a[i]-b[i];
End;
End;
Bài 3 So sánh 2 số lớn
Input: S1, S2 2 số có số chữ số <=200
Output: sắp xếp lại 2 xâu để S1>=S2
Trang 3Prorcedure sosanh(X,Y: string; Var biger, equal, less: Boolean);
Begin
biger:=false; equal:=false; less:=false; nx:=length(X); ny:=length(Y);
If X=Y then equal:=true
Else if nx> ny then biger:=true
Else if ny> nx then less:=true
Else
Begin
i:=0;
While (X[i+1]=Y[i+1]) and (i<nx) do inc(i);
If i=nx then equal:=true;
Else if X[i]>Y[i] then Biger:=true
Else less:=true;
End;
End;
Begin{ Main}
READLN (S1,S2);
SOSANH(S,S2,big, eq,les);
If les then begin tg:=S1; s1:=s2; s2:=tg; end;
INKQ(S1, S2);
End
Bµi 4 Nh©n mét sè lín víi mét sè nguyªn d-¬ng ( trong pv m¸y tÝnh)
Input : S - X©u biÓu diÔn sè lín , n –sè nguyªn d-¬ng
Output: S.n
BEGIN
- NhËp S, nhËp n
- DOI(S,a){ doi x©u sè S thµnh m¶ng a[0],…, a[n])
- NHAN(a,n,T) { nh©n a víi n cho m¶ng tÝch T}
- GHIKQ(T);
END
PROCEDURE NHAN(a:mang; n:integer; Var T:mang);
Var
Begin
Fillchar(T,sizeof(T),0);
Nho:=0; Tg:=0;
For i:=0 to 300 do
Begin
Tg:=a[i]*n +nho;
T[i]:= Tg mod 10;
Nho:=tg div 10
End;
End;
Trang 4Bài 5 Nhân 2 số lớn
Input: 2 số S1, S2
Output S1.S2
Thuật toán:
+ Khai báo các mảng các byte: TG, KQ,a,b
+ DOI(S1,a); DOI(S2,b);
+ for i:=0 to 300 do
Begin
Nhan(a, b[i],TG);
For j:= 0 to 300 do CONG( TG, KQ, i);
End;
+ INKQ;
+ cài đặt
Procedure CONG(TG: mang; var KQ: mang; i: integer);
Var nho, t: integer;
Begin
Nho:=0; t:=0;
For j:=0 to 300 do
Begin
t:=KQ[j+i]+TG[j]+nho;
KQ[j+i]:= t mod 10;
nho:= t div 10;
End;
End;
III Các bài toán ứng dụng
Bài 1 Giai thừa
Input : n nguyên d-ơng n<=200
Output:Tính giai thừa n!
Thuật toán:
+ Khai báo mảng : GT[0 1000] of byte { chứa kết quả};
+ Khởi tạo a[0]:=1
+ For i:=1 to n do NHAN(i, a); {Chú ý đầu tiên khởi tạo a[0]:=1} + GHIKQ
Trang 5Bài 2 Tổng luỹ thừa
Thuật toán:
+ Xây dung thủ tục PROCEDURE LT(K, n: integer, var A:mang); {nâng K lên luỹ thừa n, kết quả ghi vào mảng A}
For i:=1 to n do NHAN( K,a) {chú ý đầu tiên khởi tạo a[0]:=1}
+ Gọi thủ tuc LT(P,n,A), LT(Q.m,B)
+Gọi thủ tuc CONG(A, B, C);
+ Ghi C
Bài 3 Ghép HCN
Input: a , b, c , d , với a,b,c,d nguyên d-ơng là kích th-ớc 2 hình chữ nhật a x
b và c x d Hỏi từ 2 hcn đó có thể ghép đ-ợc thành một hcn Output : 2 hcn đó
có thể ghép đ-ợc thành một hcn khác Nếu ghép đ-ợc cho biết chu vi lớn nhất
có thể
Bài 4 BCNN
Tìm BCNN(a1,a2,…,an) (Đề thi HSG Hà nội 2010)
Thuật toán:
+ Xét dãy các số nguyên tố trong khoảng tứ 2 đến n:
Snt:=0;
For p:=2 to n do
If OK (P) then {if P nguyên tô}
Begin
Inc(snt)
NT[snt]:=p;
+ Xét dãy số mũ max của số nguyên tố NT[i] là -ớc của a1,a2,
Khởi tạo Mmax[i]:=0;(i=1 snt)
+ for i:= 1 to n do {xét a1, a2,…}
Begin
Tg:=a[i];
For j:= 1 to snt do
Begin
mm:=0
While tg mod nt[j] =0 do
Begin
Tg:= tg div nt[j];
Inc(mm)
Trang 6End;
If mm>mmax[j] then mmax[j]:=mm;
End;
End;
+ Gäi m¶ng bc[0], bc[1],,,bc[300] lµ BCNN (ghi theo tt ng-îc) +Khëi tao bc[0]:=1
+
For i:=1 to snt do
If mmax[i]>0 then
For j:= 1 to mmax[i] do nhan (bc, nt[i])
+ GHI gäi nbc: chØ sè kh¸c kh«ng cuèi cïng cña bc
For nbc:=300 downto 0 do if bc[nbc]<>0 then break;
For i:= nbc downto 0 do write(BC[I]);
End