Kỹ năng dùng mảng một chiều để xử lý số nguyên lớn giúp giải các bài toán khó trong lập trình pascal

22 184 0
Kỹ năng dùng mảng một chiều để xử lý số nguyên lớn giúp giải các bài toán khó trong lập trình pascal

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

Thông tin tài liệu

MỤC LỤC A MỞ ĐẦU ……………………………………………………………… I Lí chọn đề tài ………………………………………………………… II mục đích nghiên cứu ……………………………………… …………… III Đối tượng nghiên cứu …………………………………….…………… IV Phương pháp nghiên cứu ……………………………………………… B NỘI DUNG I Cơ sở lí luận ……………………………………………………………… II Thực trạng vấn đề trước áp dụng …………………………………… III Giải pháp sử dụng ……………………………………………………… Phần một: XÂY DỰNG CÁC PHÉP TOÁN SỐ HỌC TRÊN SỐ LỚN … 1.1 Biểu diễn số nguyên lớn……………………………………………… 1.2 Xây dựng phép toán số học ……………………………………… 1.2.1 Phép so sánh ………………………………………………………… 1.2.2 Phép cộng số lớn với số nhỏ ……………………………… 1.2.3 Cộng hai số nguyên lớn ……………………………………………… 1.2.4 Phép trừ ……………………………………………………………… 1.2.5 Phép nhân số lớn với số nhỏ ……………………………… 1.2.6 Phép nhân hai số nguyên lớn ………………………………………… 1.2.7 Phép chia số nguyên lớn cho số nguyên nhỏ (lấy phần thương nguyên (div) dư (mod)) ………………………………………… 1.2.8 Phép chia hai số nguyên lớn (lấy phần thương nguyên (div) dư (mod)) ……………………………………………………………………… Phần hai: MỘT SỐ BÀI TOÁN ỨNG DỤNG XỬ LÝ SỐ LỚN ……… 2.1 Bài tốn Tính giai thừa ……………………………….……………… 2.2 Bài toán (Đề Bảng C Tin học trẻ khơng chun tồn quốc) ….……… 2.3 Bài tốn (Đề thi OLIMPIC Tin học sinh viên Việt Nam 2005) ….… 2.4 Bài toán (Đề thi OLP 2004) ……………………………………… Phần ba: tập luyện tập ……………………………………………… … IV Hiệu sáng kiến ………………………………………………… C KẾT LUẬN, KIẾN NGHỊ …………………………………………… I Kết luận ………………………………………………………………… II Kiến nghị ………………………………………………………………… 2 2 3 3 5 6 7 8 9 10 12 15 18 20 21 21 21 A MỞ ĐẦU I Lí chọn đề tài Trong ngơn ngữ lập trình thường có số kiểu liệu chuẩn cho biết phạm vi giá trị lưu trữ, dung lượng nhớ cần thiết để lưu trữ xác định phép tốn tác động lên liệu Chẳng hạn Turbo Pascal, số kiểu liệu dạng số nguyên bao gồm: byte, integer, word, longint, int64, qword Trong kiểu qword có phạm vi lớn nhất, giá trị lưu trữ byte cho phép biến lưu số tối đa có 20 chữ số Tuy nhiên thực phép tính với số ngun ngồi phạm vi biểu diễn cung cấp (có nhiều 20 chữ số) ta cần thiết kế cách biểu diễn hàm thực phép toán với số nguyên lớn Gần kỳ thi học sinh giỏi người ta thường hay đưa toán cần kết hợp xử lý số lớn Vì tìm hiểu biểu diễn số lớn phép tốn với số lớn cần thiết Trong khn khổ đề tài này, đưa cách biểu diễn số ngun khơng âm lớn phép tốn Cụ thể Tên đề tài: “KỸ NĂNG DÙNG MẢNG MỘT CHIỀU ĐỂ XỬ LÝ SỐ NGUYÊN LỚN GIÚP GIẢI CÁC BÀI TỐN KHĨ TRONG LẬP TRÌNH PASCAL” II Mục đích đề tài Sử dụng ví dụ cụ thể số nguyên lớn để học sinh nắm phương pháp chuyển đổi Và thơng qua ví dụ hướng dẫn học sinh làm số tốn ứng dụng sử lí số ngun lớn III Đối tượng nghiên cứu Học sinh giỏi khối 11 trường THPT NGỌC LẶC Sử dụng máy tính để chạy chương trình IV Phương pháp nghiên cứu - Kết hợp thực tiễn việc ôn luyện học sinh giỏi trường THPT THPT NGỌC LẶC - Có tham khảo tài liệu ngơn ngữ lập trình Pascal tài liệu sáng kiến kinh nghiệm B NỘI DUNG I.Cơ sở lí luận Khi giải toán số pascal ta dùng kiểu liệu sau: byte, integer, word, longint, int64, qword kiểu qword có phạm vi lớn cho phép biến lưu số tối đa có 20 chữ số Khi số nguyên lớn vượt qua giới hạn (ví dụ số nguyên 21 số trở lên) việc lưu trữ kiểu liệu điều khơng thể II Thực trạng vấn đề trước áp dụng Thuận lợi: Được quan tâm Sở Giáo dục & Đào tạo Ban giám hiệu nhà trường, mơn Tin học trang bị phòng máy tính với máy chiếu phục vụ cho nhu cầu công tác giảng dạy ứng dụng CNTT giáo viên Khó khăn Chất lượng đầu vào khơng cao, trường THCS còn học sơ sài kiến thức tin học, Ngơn ngữ Pascal ngơn ngữ khó trừu tượng học sinh, Những toán nâng cao còn khó khả học sinh dẫn đến học sinh cảm thấy sợ gặp dạng toán đó, từ khơng u thích mơn III.Giải pháp sử dụng Phần một: XÂY DỰNG CÁC PHÉP TOÁN SỐ HỌC TRÊN SỐ LỚN 1.1 Biểu diễn số nguyên lớn Thông thường người ta sử dụng cách biểu diễn số nguyên lớn sau: Xâu kí tự: Mỗi kí tự xâu tương ứng với chữ số số nguyên lớn tính từ trái qua phải Mảng số: Sử dụng mảng lưu chữ số (hoặc nhóm chữ số) số nguyên lớn Danh sách liên kết số: Sử dụng danh sách liên kết chữ số (hoặc nhóm chữ số) Ở đây, ta xét cách biểu diễn thứ hai, biểu diễn số nguyên lớn mảng, phần tử mảng chữ số số xét với số nguyên lớn không âm Khai báo Const Maxn=1000; Type Chuso=0 9; Bigint=Array[1 maxn] of chuso; Var X,a,b: Bigint; Để dễ dàng thực phép toán ta lưu mảng theo thứ tự ngược lại với số, tức chữ số mảng lưu theo chiều từ trái sang phải: chữ số hàng đơn vị phần tử thứ nhất, chữ số hàng chục phần tử thứ hai, … Ví dụ: số X = 1965 mảng X là: (5,6,9,1,0,0,0…) tức X[1] = 5; X[2] = 6; X[3] = 9; X[4] = 1; X[5] = 0,… Dữ liệu vào: Gồm hai số nguyên lớn số nguyên lớn số nguyên nhỏ (số nhỏ số có kiểu chuẩn: byte, integer, word, longint…), hai số cách dòng trống, số nguyên lớn ghi nhiều dòng Thủ thục đọc file liệu vào gồm hai số nguyên lớn: procedure readf; var s:string; so:chuso; code,i,n:integer; begin assign(f,fi); reset(f); ma:=0; fillchar(a,sizeof(a),0); {a số nguyên lớn} mb:=0; fillchar(b,sizeof(b),0); {b số nguyên lớn} repeat readln(f,s); ma:=ma+length(s); until s=''; repeat readln(f,s); mb:=mb+length(s); until s=''; close(f); reset(f); n:=ma; {ma độ dài số a} repeat readln(f,s); for i:=1 to length(s) begin val(s[i],so,code); a[n]:=so; n:=n-1; end; until s=''; n:=mb; {mb độ dài số b} repeat readln(f,s); for i:=1 to length(s) begin val(s[i],so,code); b[n]:=so; n:=n-1; end; until s=''; close(f); end; Thủ tục đọc file liệu vào gồm số nguyên lớn số nguyên nhỏ procedure readf; var s:string; so:chuso; code,i,n:integer; begin assign(f,fi); reset(f); ma:=0; fillchar(a,sizeof(a),0); {a số nguyên lớn} repeat readln(f,s); ma:=ma+length(s); until s=''; close(f); reset(f); n:=ma; repeat readln(f,s); for i:=1 to length(s) begin val(s[i],so,code); a[n]:=so; n:=n-1; end; until s=''; readln(f,num); {num số nguyên nhỏ} close(f); end; 1.2 Xây dựng phép toán số học 1.2.1 Phép so sánh Để so sánh hai số nguyên lớn a, b ta so sánh độ dài hai số Nếu hai số có độ dài so sánh chữ số hai số Hàm cmp trả giá trị a lớn b, trả giá trị -1 a nhỏ b trả giá trị a b Function cmp(a,b:bigint):integer; Var i:integer; Begin If ma>mb then begin cmp:=1; exit; end Else if mab[i] then begin cmp:=1; exit; end Else if a[i]0 begin ma:=ma+1; tong[ma]:=nho mod 10; nho:=nho div 10; for k:=1 to ma begin t:=a[k]+nho; nho:=t div 10; tong[k]:=t mod 10; if nho=0 then break; end; end; end; Chú ý: Trong Turbo Pascal kết trả lại hàm kiểu sở như: số nguyên, số thực, kí tự, kiểu xâu Nếu muốn trả lại kết kiểu cấu trúc mảng có cách dùng tham biến Nhưng Free Pascal cho phép kết hàm kiểu cấu trúc Như viết Free Pascal ta thay thủ tục cộng hàm cộng hai số 1.2.3 Cộng hai số nguyên lớn Thuật tốn: Như phép cộng thơng thường học thực giấy (cộng chữ số từ bậc thấp đến bậc cao, có nhớ) Procedure cong( a,b:bigint;Var begin tong:bigint ); t:=t+a[i]+b[i]; var i,t:longint; tong[i]:=t mod 10; begin t:=t div 10; if ma >=mb then begin max:=ma; for end; i:=mb+1 to ma b[i]:=0; end if t>0 then begin max:=max+1; else begin max:=mb; for i:=ma+1 to tong[max]:=t; end; mb a[i]:=0; end; end; t:=0; fillchar(tong,sizeof(tong),0); for i:=1 to max 1.2.4 Phép trừ Thuật toán: dùng thuật toán trừ kiểu thủ công (trừ chữ số từ bậc thấp đến bậc cao, có nhớ) Có hai trường hợp: - Trường hợp a>b thực a trừ cho b - Trường hợp a1) and (kq[max]=0) for i:=1 to max do max:=max-1; end; 1.2.5 Phép nhân số lớn với số nhỏ Thuật toán: Nhân số lớn x với số nhỏ num Ta không cần quan tâm num có chữ số coi số có chữ số nhân với chữ số số lớn x từ phải sang trái, nhớ lớn procedure nhan (x:bigint; num:longint; while nho>0 var tich:bigint); begin var t,nho,k:longint; max:=max+1; begin tich[max]:=nho mod 10; nho:=0; nho:=nho div 10; for k:=1 to max {max độ dài end; số lớn x} end; begin t:=num*x[k]+nho; nho:=t div 10; tich[k]:=t mod 10; end; 1.2.6 Phép nhân hai số nguyên lớn Thuật toán: Như phép nhân thơng thường học thực giấy Ví dụ: Theo ta thấy việc nhân hai số gồm hai thao tác: 352 × Thao tác 1: Thực việc nhân chữ số (từ phải sang 18 trái hết) số thứ hai với số thứ 2816 Thao tác 2: Thực phép cộng tất số vừa tính + 352 procedure 6336 procedure nhan2so(a,b:bigint; var tich:bigint); {tích hai số lớn} var x:bigint; j,k,l:integer; begin j:=0;fillchar(kq,sizeof(kq),0); for k:=1 to mb begin nhan(a,b[k],tich1); {tích số lớn a với chữ số b} for l:=1 to j chen(0,tich1); cong(kq,tich1,tich); {cộng dồn số tính được} kq:=tich; j:=j+1; end; end; 1.2.7 Phép chia số nguyên lớn cho số nguyên nhỏ (lấy phần thương nguyên (div) dư (mod)) Thuật toán chia số lớn cho số nhỏ thao tác từ trái qua phải, lần hạ phần tử xuống, gộp vào biến nhớ, thực phép chia trực tiếp (vì số chia số nhỏ) Procedure chia( a:bigint; if nho>=num then begin i:=i+1; num:longint;var thuong:bigint;var thuong[i]:=nho div num; end; du:longint); nho:=nho mod num; var nho,k,i,j:longint; end; begin du:=nho; max:=i; nho:=0; k:=ma; i:=0; {Xóa số đầu số thuong} while k>=1 while (thuong[1]=0) and (max>1) begin begin while (nho=1) for j:=1 to max-1 begin thuong[j]:=thuong[j+1]; nho:=nho*10+a[k]; max:=max-1; if nho=1 begin while (not ss(du,b)) and (k>=1) {cat lan luot tung doan cua so bi chia} begin chen(a[k],du); if not ss(du,b) then begin i:=i+1;thuong[i]:=0; end; dec(k); end; if ss(du,b) then {hàm ss(du,b) trả giá trị true du>=b} begin t:=0; {dem chia bang phep tru} while ss(du,b) begin inc(t); tru(du,b);{thủ tục tru(a,b)thực trừ du cho b, kết trả lại lưu vào du} end; inc(i);thuong[i]:=t; end; end; m:=i; {m độ dài thuong} {Xóa số đầu số thuong} while (thuong [1]=0) and (m>1) begin for j:=1 to m-1 thuong[j]:=thuong[j+1]; m:=m-1; end; end; Phần hai MỘT SỐ BÀI TOÁN ỨNG DỤNG XỬ LÝ SỐ LỚN 2.1 Bài toán Tính giai thừa Hãy tính N! (N3 Yêu cầu: Hãy xác định độ dài lớn dãy thỏa mãn giá trị số hạng nhỏ hay giá trị nguyên k cho trước Dữ liệu vào: từ file văn DAYSO.INP gồm dòng chứa không 255 chữ số viết liền (khơng có số vô nghĩa đầu) biểu diễn giá trị k Kết quả: Ghi file văn DAYSO.OUT độ dài lớn dãy tìm Ví dụ DAYSO.INP DAYSO.OUT 41 12 Thuật toán: Tạo dần số dãy thỏa mãn tính chất Do giá trị số nguyên K lớn (255 chữ số) Vì để tạo số dãy ta cần sử dụng phép toán cộng hai số lớn const fi='dayso.inp'; go='dayso.out'; type bigint=array[1 1000] of byte; var a,b,c,d,k:bigint; S:array[1 1000] of char; dem,p,l:integer; thoat:boolean; f,g:text; 10 procedure Openf; begin assign(f,fi); reset(f); assign(g,go); rewrite(g); end; {================================================} procedure Closef; begin close(f); close(g); end; {=============================================} procedure Input; var i:integer; begin l:=0; while not eoln(f) begin l:=l+1; read(f,s[l]); end; for i:=1 to l k[i]:=ord(s[l-i+1])-48; end; {=============================================} procedure cong(a,b:bigint; var c:bigint); var i,t:longint; begin t:=0; for i:=1 to p begin t:=t+a[i]+b[i]; c[i]:=t mod 10; t:=t div 10; end; if t>0 then begin p:=p+1;c[p]:=t;end; end; {==============================================} function Lonhon:boolean; var i:integer; begin if pl then begin Lonhon:=true; exit; end else 11 for i:=p downto if k[i]>d[i] then begin lonhon:=false; exit; end else if k[i]m then m:=j; End; End; 2.4 Bài toán (Đề thi OLP 2004) Gọi X tập tất xâu nhị phân khơng có đánh thứ tự theo trình tự sinh (từ nhỏ đến lớn, bit đứng trước bit 1) Chẳng hạn với n=5 ta có xâu sau: Bài toán đặt ra: Hãy xác định xâu nhị phân n bit ứng với số thứ tự m cho trước Hạn chế: n0 then begin max:=max+1; kq[max]:=t; end; end; {===============================================} Function sosanh(var a,b:bigint; na,nb:byte):boolean; var i:byte; Begin sosanh:=true; if nanb then begin sosanh:=false; exit; end else for i:=na downto if a[i]b[i] then begin sosanh:=false; exit; end; End; {===============================================} procedure tru(var a,b:bigint; var na,nb:byte); var i,nho,max:longint; begin if na >=nb then begin max:=na; for i:=nb+1 to na b[i]:=0; end else begin max:=nb; for i:=na+1 to nb a[i]:=0; end; nho:=0; for i:=1 to max begin nho:=a[i]-b[i]-nho; if nho1) and (a[max]=0) dec(max); na:=max; end; {===============================================} Procedure Process; var i,j:integer; Begin For i:=3 to n cong(L[i-1],l[i-2],L[i],cd[i-1],cd[i-2],cd[i]); for i:=n downto If sosanh(m,L[i-1],mm,cd[i-1]) then x[i]:=0 else Begin x[i]:=1; tru(m,l[i-1],mm,cd[i-1]); end; End; procedure writef; var i:integer; begin assign(f,fo); rewrite(f); for i:=n downto write(f,x[i]); close(f); end; {===============================================} BEGIN readf; process; writef; END Phần 3: Bài tập luyện tập Bài Tính MN (M, N

Ngày đăng: 21/10/2019, 20:28

Từ khóa liên quan

Mục lục

  • 1. Thuận lợi:

  • Khi đã nắm vững nhiều dạng thuật giải kết hợp với kỹ năng lập trình tốt thì chúng ta có thể giải nhiều bài toán tin học khác nhau. Chẳng hạn khi có thuật toán tốt nhưng do bài toán yêu cầu với dữ liệu rất lớn thì ta phải có kỹ năng làm việc tốt với số lớn thì sẽ vượt qua các test lớn. Tuy nhiên nếu không biết sử dụng một cách linh hoạt thì chương trình chạy chậm và tốn nhiều bộ nhớ. Vì vậy cần có các kỹ thuật xử lý số lớn tốt để giảm bớt các phép tính và biến lưu trữ.

  • Bản thân là một giáo viên đứng lớp đã từng ôn luyện học sinh giỏi, tôi luôn trăn trở rằng làm thế nào để nâng cao chất lượng của bộ môn góp phần nâng cao chất lượng giáo dục chung của nhà trường. Từ đó tôi đã áp dụng phương pháp như đã trình bày ở trên, ban đầu do học sinh chưa quen nên cũng gặp khó khăn. Nhưng sau một thời gian thực hiện cũng đã cho kết quả khá khả quan. Học sinh hứng thú học, ham học, yêu thích môn học, tiếp thu bài tốt hơn và có thể dễ dàng giải quyết được các bài toán liên quan đến số nguyên lớn.

  • II. Kiến nghị

Tài liệu cùng người dùng

  • Đang cập nhật ...

Tài liệu liên quan