Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 23 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
23
Dung lượng
175 KB
Nội dung
SÁNG KIẾN KINH NGHIỆM SỬDỤNGKIỂUDỮLIỆUXÂUĐỂXỬ LÍ CÁCBÀITOÁNCẦNXỬ LÍ DỮLIỆUSỐLỚN I ĐẶT VẤN ĐỀLý chọn sáng kiến kinh nghiệm: Khi gặp toán có yêu cầu xửlýsố nguyên có giá trị lớn Pascal ta thường gặp phải số lỗi: lỗi tràn ngăn xếp stack overflow error; lỗi vượt phạm vi khai báo Range check error; lỗi tràn vùng nhớ Heap Heap overflow error chương trình không thực Hằng năm, kỳ thi học sinh giỏi tỉnh thường gặp toáncầnxửlýliệusốlớn với số lượng test lớn đòi hỏi thí sinh phải tìm cách đểxử lí( Nếu không sửdụng Free Pascal) Vấn đề đặt phải tìm số phương pháp xử lí sốlớn mà tránh gặp phải lỗi gặp Trong phạm vi sáng kiến này, xin giới thiệu sốtoán phải xử lí số nguyên có giá trị lớn cách lưu trữ (đọc) chúng dạng kiểuliệuxâu Ngoài ra, việc sửdụngkiểuliệuxâu giúp người lập trình có nhiều thuận tiện việc xử lí Điều toán cụ thể mà sáng kiến kinh nghiệm có đệ cập đến Mục đích nghiên cứu: Sáng kiến kinh nghiệm nghiên cứu nhằm mục đích phục vụ công tác giảng dạy bồi dưỡng học sinh giỏi trường, học sinh giỏi tỉnh, học sinh thi tin học trẻ Ngoài sáng kiến kinh nghiệm sửdụng làm chuyên đề báo cáo cấp tổ Sáng kiến kinh nghiệm ưu điểm kiểuliệuxâu việc ứng dụngđể giải toán yêu cầu xử lí liệusốlớnKiểuliệuxâukiểuliệuđề cập đầy đủ, chi tiết, sáng tỏ sách giáo khoa tin học 11 tài liệu tham khảo khác Đối tượng nghiên cứu: Kiểuliệuxâu thao tác xử lí xâu Cách vận dụngkiểuliệuxâuđể thay kiểuliệusố Một số dạng tập liên quan đến sáng kiến kinh nghiệm Thuật toánđể giải sốtoán tiêu biểu Đối tượng khảo sát , thực nghiệm: Học sinh khối 11 học xong 12 kiểuliệu xâu, học sinh giỏi trường, đội tuyển học sinh giỏi tỉnh, đội tuyển thi tin học trẻ đồng nghiệp Phương pháp nghiên cứu: Đi từ nhu cầu thực tiễn công tác giảng dạy, đặc biệt công tác bồi dưỡng học sinh giỏi Cụ thể qua toánxử lí liệusố lớn, để tìm cách xử lí đơn giản, hiệu Đó cách sửdụngkiểuliệuxâu Vận dụng kiểm tra tính hiệu quả, tính tối ưu phương pháp Từ bước xây dựng nên sáng kiến kinh nghiệm Tóm lại , phương pháp nghiên cứu từ thực tiễn đến lí luận, từ lí luận quay phục vụ thực tiễn Phạm vi kế hoạch nghiên cứu: Sáng kiến kinh nghiệm thực theo kế hoạch ban chuyên môn nhà trường, bắt bầu từ tháng /2016 đến tháng 5/2017, kết tích luỹ nhiều năm dạy học bồi dưỡng học sinh giỏi tỉnh II NỘI DUNG Cơ sở lí luận: Kiểuliệuxâu dãy hữu hạn kí tự mã ASCII Mỗi kí tự phần tử xâuSố lượng phần tử xâu gọi độ dài xâu Độ dài tối đa xâu 255 Một số nguyên lớn xem “một xâu” mà phần tử kí tự thuộc phạm vi [’0’ ’9’] Ngoài ra, phép so sánh chữ số áp dụngđểso sánh kí tự số Do việc ứng dụngkiểuliệuxâu vào xử lí liệusố thuận lợi cho phép xử lí sốlớn có số chữ số lên tới 255 số Tuy nhiên, phần tử xâu kí tự nên không áp dụng phép toánsố học lên Việc giải đơn giản cách sửdụng hàm, thủ tục xử lí xâu mà học sinh trang bị sẵn Việc sửdụngkiểuliệuxâuđể giải toán có liệusốlớn thường thực qua bước sau: B1 Đọc số dạng xâu; B2 Xử lí phần tử xâu tuỳ vào yêu cầu cụ thể toán; B3 Đưa kết toán Thực trạng giải pháp: Sau toánsửdụngkiểuliệuxâuđể giải có so sánh tính hiệu phương pháp với số phương pháp khác BàitoánSỐ ĐƠN ĐIỆU_Bài Đề thi hsg tỉnh lớp 11 bảng A năm học 2013-2014 Số a1, a2, …, aN gọi số đơn điệu < ai+1 > ai+2 > ai+1 < ai+2 (i:=1N-2) Số có chữ số, số có hai chữ số khác gọi số đơn điệu có độ dài 1, Yêu cầu: Viết chương trình xác định số chữ sốlớn tạo thành số đơn điệu biểu diễn số cho trước Dữ liệu: Vào từ tệp văn bai1.inp số nguyên dương N (N có số chữ số < 256 ) Dữliệu ra: Ghi tệp văn bai1.out số nguyên, số chữ sốlớn tạo thành đoạn số đơn điệu số N Nếu đoạn số đơn điệu ghi số VD: Bai1.inp Bai1.out 13243544446666 - Xác định toán: • Input: Số nguyên dương N • Output: Số chữ sốlớn tạo thành đoạn số đơn điệu N - Ý tưởng thuật toán: Đọc N dạng xâu s Ta xét tất đoạn biểu diễn N có độ dài giảm dần từ số lượng chữ số N 1(Xét đoạn xâu s có độ dài giảm từ độ dài xâu s 1) Mỗi đoạn xét thoả mãn điều kiện toán đưa độ dài đoạn thoát Sửdụng hàm để kiểm tra đoạn có thoả mãn điều kiện toán hay không - Chương trình tham khảo program bai1; const fi='bai1.inp'; fo='bai1.out'; var s:string; i,l:byte; f,g:text; procedure motep; begin assign(f,fi);reset(f); assign(g,fo);rewrite(g); end; function kt(m,n:byte):boolean; var p:word; begin kt:=true; for p:=m to n+m-2 if ((s[p]>=s[p+1]) and (s[p+1]>=s[p+2])) or ((s[p]s[max] then max:=i; End; Procedure Begin End; Begin xuli; readln(f,s); read(f,k); P:=’’; While (k>0) and (length(s)>0) Begin I:=max(k); P:=p+s[i]; Delete(s,1,i); K:=k-i+1; End; If k=0 then p:=p+s; Write(g,‘ solon nhat tim duoc la: ‘, p); Close(f); close(g); motep; Xuli; End Bàitoán Cho số nguyên dương N, tìm biểu diễn nhị phân N Dữliệu vào: Từ tệp văn Bai7.inp số, số nguyên N Dữliệu ra: Ghi lên tệp văn Bai7.out biểu diễn nhị phâ số N VD Bai7.inp Bai7.out Bai7.inp Bai7.out 125 01111111 255 11111111 - Xác định toán: + Input: Số nguyên dương N + Output: Biểu diễn nhị phân số N - Ý tưởng thuật toán: Cách 1: Sửdụng mảng chiều để lưu sốdư phép chia N cho 2, sau lần chia N gán lại với giá trị N chia Quá trình kết thúc N=0 Sau đưa phần tử mảng theo thứ tự từ phần tử có sốlớn đến phần tử có số nhỏ Để xác định số cuối mảng chiều ta dùng biến kiểu nguyên d Ban đầu d:=0, sau lần chia lấy dư N cho ta tăng biến d lên đơn vị Cách Sửdụng biến xâu s để lưu sốdư phép chia N cho Ban đầu s:=’’, sau lần lấy sốdư phép chia N cho 2, ta chuyển sang kiểuxâu ghép vào biến xâu s Dạng nhị phân N xâu ngược s - Chương trình tham khảo Theo cách program bai7c1; const maxd=100; 11 fi=’bai7.inp’; fo=’bai7.out’; var N:word; i,d:byte;f,g:text; a:array[1 maxd] of byte; procedure motep; begin assign(f,fi);reset(f); assign(g,fo);rewrite(g); end; procedure xuli; begin readln(f,N); d:=0; while N>0 begin inc(d); a[d]:=N mod 2; N:=N div 2; end; for i:=d downto write(g,a[i]); close(g); close(f); end; Begin motep; Xuli; End Theo cách program bai7c2; const fi=’bai7.inp’; fo=’bai7.out’; var N:word; i:byte; s,x:string; f,g:text; procedure motep; begin assign(f,fi);assign(g,fo); reset(f); rewrite(g); end; procedure xuli; begin read(f,N); s:=''; while N>0 12 begin i:=N mod 2; N:=N div 2; str(i,x);s:=s+x; end; write(g,s); close(g); close(f); end; Begin motep; Xuli; End Nhận xét: Ta thấy thuật toán tương xâu xem mảng chiều mà phần tử kí tự Tuy nhiên thuật toán ta phải xác định số lượng phần tử thực mảng a, tức xác định giá trị biến d Còn với thuật toán không cầnđể xác định số lượng phần tử xâu s ta dùng hàm length(s) Bàitoán Cho số nguyên dương N, xếp số biểu diễn N đểsốlớnDữliệu vào: Từ tệp văn Bai8.inp số, số nguyên N Dữliệu ra: Ghi lên tệp văn Bai8.out số, số xếp VD Bai8.inp Bai8.out 846759624 987665442 - Xác định toán: + Input: Số nguyên dương N + Output: Sốlớn xếp biểu diễn số N - Ý tưởng thuật toán: Cách 1: Sửdụng mảng chiều để lưu số có biểu diễn N(Với N nhỏ) Để lấy số có biểu diễn N, ta dùng phép chia N mod 10, sau lần chia N gán lại với giá trị N div 10 Quá trình kết thúc N=0 Sau đưa phần tử mảng theo thứ tự từ tăng dần Để xác định số cuối mảng chiều ta dùng biến kiểu nguyên d Ban đầu d:=0, sau lần chia lấy dư N cho 10, ta tăng biến d lên đơn vị Cách 2: Sửdụng biến xâu s để lưu N( đọc N dạng xâu) Sau ta đưa phần tử xâu s theo thứ tự giảm dần - Chương trình tham khảo Theo cách program bai8c1; const fi=’Bai8.inp’; fo=’Bai8.out’; var N:longint; i,j,d:byte; f,g:text; a:array[1 100] of byte; 13 procedure motep; begin assign(f,fi); reset(f); assign(g,fo);rewrite(g); end; procedure xuli; begin read(f,N); d:=0; while N>0 begin inc(d); a[d]:=N mod 10; N:=N div 10; end; for j:=9 downto for i:= to d if a[i]=j then write(g,a[i]); close(f); close(g); end; Begin Motep; Xuli; End Theo cách program bai8c2; var N:word; i:byte; j:char; s,x:string; begin write('nhap N='); readln(N); s:=''; while N>0 begin i:=N mod 10; N:=N div 10; str(i,x);s:=s+x; end; write('so lon nhat bieu dien cua N la:'); for j:='9' downto '0' for i:= to length(s) if s[i]=j then write(s[i]); 14 readln end Nhận xét: Theo cách 1, ta thấy phần tử mảng a theo thứ tự số đảo ngược N giá trị N bị thay đổi (giá trị =0) Việc giữ lại giá trị N thực cách gán giá trị cho biến khác Nhìn chung ý tưởng cách giải không khác nhiều BàitoánSố đối xứng số mà ta đọc chữ số từ trước sau hay theo thứ tự ngược lại có kết Cho hai số nguyên dương M, N ( Mt div ) then dx:=true else dx:=false; end; begin write('nhap M,N='); readln(M,N); dem:=0; for B:= M to N begin str(B,s); if dx(s) then inc(dem); end; write('so luong so doi xung co doan M, N la:', dem); readln end Nhận xét: Theo cách 1, ta thấy phần tử mảng chiều a theo thứ tự số đảo ngược B1 giá trị B1 bị thay đổi Do ta phải sửdụng thêm biến B để lưu lại giá trị B1 Nói chung cách phức tạp 16 Còn theo cách 2, ta thấy thuật toán rõ ràng đơn giản hơn, chương trình ngắn Bàitoán 10 Nhập từ bàn phím số M gồm chữ số M biểu diễn nhị phân số nguyên dương N Tìm đưa hình số nguyên dương N Dữliệu vào: Từ tệp văn Bai10.inp số, số nguyên M Hai số cách dấu cách Dữliệu ra: Ghi lên tệp văn Bai10.out số, số nguyên dương N VD Bai10.inp Bai10.out Bai10.inp Bai10.out 01111111 125 10000000 128 - Xác định toán: + Input: Số M gồm chữ số 1; + Output: Số nguyên dương N mà biểu diễn nhị phân M - Ý tưởng thuật toán: Cách Tách số M, lần tách số ta cộng tích số với lũy thừa với số mũ tương ứng vào tổng, đồng thời gán lại giá trị cho M M=M div 10 Quá trình kết thúc M=0 Giá trị tổng N Để tính lũy thừa số 2, ta sửdụng chương trình luythua Cách Dùng biến xâu s, sau chuyển M sang xâu s Gán L:=length(s); Cho i:=L-1 tới 0, thực tính tổng:=tổng +j*lũy thừa với số mũ i Với j kết thủ tục val(s[i],j,code) Để tính lũy thừa số 2, ta sửdụng chương trình luythua - Chương trình tham khảo Theo cách program bai10c1; var tong:word; M,N:word; d:integer; function luythua(i:byte):word; var j:byte;lt:word; begin if i=0 then lt:=1 else begin lt:=1; for j:=1 to i lt:=lt*2; end; luythua:=lt; end; begin write('nhap M=');readln(M); tong:=0; d:=-1; while M>0 17 begin inc(d); tong:=tong+(M mod 10)*luythua(d); M:=M div 10; end; N:=tong; write(' gia tri cua N la:',N); readln; end Theo cách program bai10c2; var tong:word; M,N:word; l,j,i:byte; s:string; code,d:integer; function luythua(i:byte):word; var j:byte;lt:word; begin if i=0 then lt:=1 else begin lt:=1; for j:=1 to i lt:=lt*2; end; luythua:=lt; end; begin write('nhap M=');readln(M); str(M,s);tong:=0;L:=length(s); d:=-1; for i:=l downto begin inc(d); val(s[i],j,code); tong:=tong+j*luythua(d); end; N:=tong; write(' gia tri cua N la:',N); readln; end Nhận xét: Theo cách 1, ta thấy chưa xác định số lượng chữ số có M nên lập trình ta phải sửdụng câu lệnh while-do 18 Còn theo cách 2, sau đổi M sang kiểuliệuxâu thông qua hàm length(s) ta xác định số chữ số M nên lập trình ta dùng câu lệnh For-do Tuy nhiên theo cách ta phải dùng thêm thủ tục Val(s[i],j,code) Đây thủ tục hay gặp việc giải sốtoán Với học sinh đội tuyển HSG GV phải trang bị cho HS thủ tục Bàitoán 11 Cho số nguyên dương N(N