Sử dụng kiểu dữ liệu xâu để xử lý các bài toán cần xử lý dữ liệu số lớn

23 511 1
Sử dụng kiểu dữ liệu xâu để xử lý các bài toán cần xử lý dữ liệu số lớn

Đ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

SÁNG KIẾN KINH NGHIỆM SỬ DỤNG KIỂU DỮ LIỆU XÂU ĐỂ XỬCÁC BÀI TOÁN CẦN XỬDỮ LIỆU SỐ LỚN I ĐẶT VẤN ĐỀ chọn sáng kiến kinh nghiệm: Khi gặp toán có yêu cầu xử 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án cần xử liệu số 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ử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ửsố nguyên có giá trị lớn cách lưu trữ (đọc) chúng dạng kiểu liệu xâu Ngoài ra, việc sử dụng kiểu liệu xâ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ểu liệu xâu việc ứng dụng để giải toán yêu cầu xửliệu số lớn Kiểu liệu xâu kiểu liệ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ểu liệu xâu thao tác xửxâu Cách vận dụng kiểu liệu xâu để thay kiểu liệu số 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ểu liệ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án xửliệu số lớn, để tìm cách xử lí đơn giản, hiệu Đó cách sử dụng kiểu liệu xâ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 DUNGsở lí luận: Kiểu liệu xâu dãy hữu hạn kí tự mã ASCII Mỗi kí tự phần tử xâu Số 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ụng kiểu liệu xâu vào xửliệu số thuận lợi cho phép xửsố lớnsố 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án số học lên Việc giải đơn giản cách sử dụng hàm, thủ tục xửxâu mà học sinh trang bị sẵn Việc sử dụng kiểu liệu xâu để giải toánliệu số 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án sử dụng kiểu liệu xâ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ài toán SỐ ĐƠ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:=1N-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,‘ so lon nhat tim duoc la: ‘, p); Close(f); close(g); motep; Xuli; End Bài toá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ố 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 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ố phép chia N cho Ban đầu s:=’’, sau lần lấy số phép chia N cho 2, ta chuyển sang kiểu xâ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ài toán Cho số nguyên dương N, xếp số biểu diễn N để số lớn Dữ 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 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ài toán Số đố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ài toá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ểu liệu xâ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ài toán 11 Cho số nguyên dương N(N

Ngày đăng: 16/08/2017, 14:52

Từ khóa liên quan

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

Tài liệu liên quan