1. Trang chủ
  2. » Giáo án - Bài giảng

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

Đ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

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ỆMSỬ 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 I.. Hằng năm, trong kỳ thi học sinh giỏi tỉnh vẫn thường gặp những bài toán cần xử lý dữ liệu

Trang 1

SÁNG KIẾN KINH NGHIỆM

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

I ĐẶT VẤN ĐỀ.

1 Lý do chọn sáng kiến kinh nghiệm: Khi gặp các bài toán có yêu cầu về xử

lý số nguyên có giá trị khá lớn trong Pascal ta thường gặp phải một 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 và khi đó chương trình không thực

hiện được

Hằng năm, trong kỳ thi học sinh giỏi tỉnh vẫn thường gặp những bài toán cần

xử lý dữ liệu số lớn với số lượng test khá 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 ra là phải tìm một số phương pháp xử lí các số lớn mà tránh gặpphải những lỗi có thể gặp như trên Trong phạm vi của sáng kiến này, tôi xin giớithiệu một số bài toán phải xử lí số nguyên có giá trị lớn bằng cách lưu trữ (đọc)

chúng dưới dạng kiểu dữ liệu xâu

Ngoài ra, việc sử dụng kiểu dữ liệu xâu còn giúp người lập trình có nhiều thuậntiện hơn trong việc xử lí Điều này cũng được chỉ ra trong từng bài toán cụ thể màsáng kiến kinh nghiệm có đệ cập đến

2 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 và 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 ra sáng kiến kinh nghiệm còn được sử dụng làmchuyên đề báo cáo cấp tổ

Sáng kiến kinh nghiệm chỉ ra ưu điểm của kiểu dữ liệu xâu trong việc ứng dụng

nó để giải các bài toán yêu cầu xử lí dữ liệu số lớn Kiểu dữ liệu xâu là kiểu dữ liệuđược đề cập khá đầy đủ, chi tiết, sáng tỏ trong sách giáo khoa tin học 11 và các tàiliệu tham khảo khác

3 Đối tượng nghiên cứu: Kiểu dữ liệu xâu và các thao tác xử lí xâu Cách vận

dụng kiểu dữ liệu xâu để thay thế kiểu dữ liệu số Một số dạng bài tập liên quanđến sáng kiến kinh nghiệm Thuật toán để giải một số bài toán tiêu biểu

4 Đối tượng khảo sát , thực nghiệm: Học sinh khối 11 đã học xong bài 12

kiểu dữ 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 tinhọc trẻ và các đồng nghiệp

5 Phương pháp nghiên cứu: Đi từ nhu cầu thực tiễn trong công tác giảng dạy,

đặc biệt là công tác bồi dưỡng học sinh giỏi Cụ thể là qua các bài toán xử lí dữ liệu

số lớn, để tìm ra cách xử lí đơn giản, hiệu quả hơn Đó là cách sử dụng kiểu dữ liệuxâu Vận dụng và kiểm tra tính hiệu quả, tính tối ưu của phương pháp Từ đó từngbướ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 là đi từ thực tiễn đến lí luận, rồi từ lí luận quay về phục vụ thực tiễn.

6 Phạm vi và kế hoạch nghiên cứu: Sáng kiến kinh nghiệm được thực hiện

theo kế hoạch của ban chuyên môn nhà trường, bắt bầu từ tháng 8 /2016 đến tháng

Trang 2

5/2017, và là kết quả tích luỹ của nhiều năm dạy học và bồi dưỡng học sinh giỏitỉnh.

II NỘI DUNG.

1 Cơ sở lí luận: Kiểu dữ liệu xâu là dãy hữu hạn các kí tự trong bộ mã ASCII.

Mỗi kí tự là một phần tử của xâu Số lượng các phần tử của xâu được gọi là độ dàicủa xâu Độ dài tối đa của xâu là 255

Một số nguyên lớn cũng được xem như là “một xâu” mà mỗi phần tử của nó là

một kí tự thuộc phạm vi [’0’ ’9’] Ngoài ra, các phép so sánh chữ số còn có thể ápdụng để so sánh các kí tự số Do đó việc ứng dụng kiểu dữ liệu xâu vào xử lí dữliệu số là khá thuận lợi và cho phép xử lí các số lớn có số chữ số lên tới 255 số.Tuy nhiên, các phần tử của xâu là các kí tự nên không áp dụng các phép toán sốhọc lên nó được Việc này được giải quyết đơn giản bằng cách sử dụng các hàm,thủ tục xử lí xâu mà học sinh đã được trang bị sẵn

Việc sử dụng kiểu dữ liệu xâu để giải quyết bài toán có dữ liệu số lớn thườngđược thực hiện qua 3 bước cơ bản như sau:

B1 Đọc số dưới dạng xâu;

B2 Xử lí các phần tử của xâu tuỳ vào yêu cầu cụ thể của từng bài toán;

B3 Đưa ra kết quả của bài toán

2 Thực trạng và giải pháp: Sau đây là những bài toán đã sử dụng kiểu dữ liệu

xâu để giải quyết và có so sánh tính hiệu quả của phương pháp này với một sốphương pháp khác

Bài toán 1 SỐ ĐƠN ĐIỆU_Bài 3 Đề thi hsg tỉnh lớp 11 bảng A năm học

2013-2014

Số a1, a2, …, aN được gọi là số đơn điệu nếu ai < ai+1 > ai+2 hoặc ai > ai+1 < ai+2

(i:=1N-2) Số có một chữ số, số có hai chữ số khác nhau cũng được gọi là số đơnđiệu lần lượt có độ dài bằng 1, 2

Yêu cầu: Viết chương trình xác định số chữ số lớn nhất tạo thành số đơn điệu

trong biểu diễn của một số cho trước

Dữ liệu: Vào từ tệp văn bản bai1.inp là một số nguyên dương N (N có số

chữ số < 256 )

Dữ liệu ra: Ghi ra tệp văn bản bai1.out một số nguyên, là số chữ số lớn nhất

tạo thành đoạn số đơn điệu của số N Nếu không có đoạn số đơn điệu thì ghi số 0

VD:

- Xác định bài toán:

Input: Số nguyên dương N.

Output: Số chữ số lớn nhất tạo thành đoạn số đơn điệu của N.

- Ý tưởng thuật toán:

Đọc N dưới dạng xâu s

Ta xét tất cả các đoạn con trong biểu diễn của N có độ dài giảm dần từ số lượngchữ số của N về 1(Xét các đoạn con của xâu s có độ dài giảm từ độ dài của xâu s

Trang 3

về 1) Mỗi đoạn con đã xét nếu thoả mãn điều kiện bài toán thì đưa ra độ dài củađoạn con đó rồi thoát.

Sử dụng hàm để kiểm tra một đoạn con có thoả mãn điều kiện bài toán haykhông

- Chương trình tham khảo

for l:=length(s) downto 3 do

begin for i:=1 to length(s)-l+1 do

if kt(i,l) then begin write(g,l+2);close(g);exit;end;

Trang 4

Dữ liệu ra: Ghi ra tệp văn bản Bai2.OUT một số, là số ở vị trí thứ N trong số

 Input: Số nguyên dương N

 Output: Số ở vị trí thứ N trong số vô hạn

+ Ý tưởng thuật toán:

Sử dụng xâu s để biểu diễn số vô hạn Trong khi độ dài của xâu s còn bé thua N thì

ta lấy các số chính phương lần lượt từ bé đến lớn rồi đổi thành xâu và ghép vào xâus

Đưa ra phần tử thứ N của xâu s(S[N])

+ Chương trình tham khảo.

Trang 5

Dữ liệu ra: Ghi lên tệp văn bản Bai3.out chỉ một số, là số chữ số của N

VD:

+/ Xác định bài toán:

- Input: Số nguyên dương N

- Output: Số chữ số có trong biểu diễn của N.

+/ Ý tưởng thuật toán:

Cách 1 Ta biết mỗi lần chia lấy phần nguyên của N cho 10 thì số chữ số mới của Ngiảm đi 1 số, ví dụ 123 div 10=12 Như vậy để đếm số lượng chữ số có trong N tachỉ cần đếm số lần gán N:=N div 10 cho đến khi N=0 Để thực hiện công việc này

ta dùng câu lệnh While_do

Cách 2 Đọc N thành xâu s Length(s) chính là số chữ số có trong biểu diễn của N

+/ Chương trình tham khảo

Trang 6

Bài toán 4 Cho số nguyên dương N, đếm xem trong N có bao nhiêu chữ số 0 ?

Dữ liệu vào: Từ tệp văn bản Bai4.inp chỉ một số, là số nguyên N.

Dữ liệu ra: Ghi lên tệp văn bản Bai4.out chỉ một số, là số chữ số 0 của N

VD

- Xác định bài toán:

+ input: Số nguyên dương N;

+ Output: Số chữ số 0 trong biểu diễn của N

- Ý tưởng thuật toán

Cách 1 Ta tách các chữ số của N từ hàng đơn vị trở lên, mỗi lần ta tách 1 số Khitách được một số thì ta kiểm tra xem số đó có phải là số 0? Nếu đúng thì tăng demlên 1 đơn vị Việc tách số được thực hiện bằng 2 phép toán mod và div

Cách 2 Đọc N thành xâu s, sau đó đếm số lần xuất hiện của kí tự ‘0’ có trong xâus

- Chương trình tham khảo:

Trang 7

For i:=1 to length(s) do if s[i]=’0’ then inc(dem);

Write(g,‘so chu so 0 co trong bieu dien cua N la:’, dem);

Còn cách 2, ta thấy độ phức tạp và trừu tường thấp vì chỉ cần kiểm tra từngphần tử của xâu xem nó có phải là kí tự ‘0’? Mặt khác sử dụng xâu để thay thế số

có thể xử lí được số rất lớn với số chữ số là 255 số

Trang 8

Bài toán 5 Cho số nguyên dương N, hãy cho biết tần số xuất hiện của mỗi chữ

số có trong N

Dữ liệu vào: Từ tệp văn bản Bai5.inp chỉ một số, là số nguyên N.

Dữ liệu ra: Ghi lên tệp văn bản Bai5.out tần số xuất hiện của mỗi chữ số từ 0

đến 9 có trong N Tần số của mỗi số trên một dòng

VD

Tan so cua 1: 6Tan so cua 2: 6Tan so cua 3: 6Tan so cua 4: 1Tan so cua 5: 1Tan so cua 6: 1Tan so cua 7: 1Tan so cua 8: 1Tan so cua 9: 0

+ Xác định bài toán:

- Input: Số nguyên dương N;

- Output: Tần số xuất hiện của mỗi chữ số có trong biểu diễn của N

+ Ý tưởng thuật toán

- Sau khi việc tách số kết thúc thì ta đưa ra các phần tử của mảng dem

Cách 2 Với N lớn

- Sử dụng một mảng một chiều dem:array[‘0’ ’9’] of byte Dem[i] dùng để đếm

số lần xuất hiện của kí tự số ‘i’ có trong trong biểu diễn dạng xâu của N

- Đọc N thành xâu sau đó đếm số lần xuất hiện của mỗi kí tự có trong xâu

- Đưa ra các phần tử của mảng dem

+ Chương trình tham khảo:

Trang 9

N:=N div 10;

End;

For i:=0 to 9 do writeln(g,‘tan so cua ‘,i, ‘ : ’,dem[i]);

For i:=’0’ to ’9’ do writeln(g,‘tan so cua ‘,i, ‘ : ’,dem[i]);

Close(g); close(f);

End;

Trang 10

- Input: Số nguyên dương N và số nguyên dương k

- Output: Số lớn nhất tìm được sau khi đã xóa đi k chữ số.

+ Ý tưởng thuật toán

- Ta thấy với N là kiểu số thì việc xóa đi k chữ số trong N là khá phức tạp Việcnày sẽ đơn giản hơn nếu N được biểu diễn dưới dạng xâu Từ đó ta đọc N sang xâus

- Để có được số lớn nhất sau khi xóa k kí tự ta có thể thực hiện như sau:

+/ Tìm kí tự lớn nhất trong k+1 kí tự đầu của xâu s Chẳng hạn kí tự s[i]

+/ Ghép kí tự tìm thấy vào xâu kết quả P, p:=p+s[i];

+/ Xóa đi i kí tự đầu của xâu s;

+/ Gán lại giá trị mới cho k, k:=k-i+1;

- Quá trình trên lặp lại cho đến khi k=0, tức là đã xóa hết k kí tự

- Sau đó lấy xâu p ghép với phần còn lại của xâu s, p:=p+s; Đổi P thành số hoặcđưa ra xâu p

+ Chương trình tham khảo

Trang 11

If s[i]>s[max] then max:=i;

Bài toán 7 Cho số nguyên dương N, hãy tìm biểu diễn nhị phân của N

Dữ liệu vào: Từ tệp văn bản Bai7.inp chỉ một số, là số nguyên N.

Dữ liệu ra: Ghi lên tệp văn bản Bai7.out biểu diễn nhị phâ của số N.

VD

- Xác định bài toán:

+ Input: Số nguyên dương N

+ Output: Biểu diễn nhị phân của số N

- Ý tưởng thuật toán:

Cách 1: Sử dụng mảng một chiều để lưu số dư của phép chia N cho 2, sau mỗi lầnchia thì N được gán lại với giá trị mới là N chia 2 Quá trình kết thúc khi N=0 Sau

đó đưa ra các phần tử của mảng theo thứ tự từ phần tử có chỉ số lớn đến phần tử cóchỉ số nhỏ nhất Để xác định chỉ số cuối của mảng một chiều ta dùng một biến kiểunguyên d Ban đầu d:=0, sau đó mỗi lần chia lấy dư N cho 2 ta tăng biến d lên mộtđơn vị

Cách 2 Sử dụng biến xâu s để lưu các số dư trong phép chia N cho 2 Ban đầus:=’’, sau đó mỗi lần lấy được một số dư trong phép chia N cho 2, ta chuyển nósang kiểu xâu và ghép vào biến xâu s Dạng nhị phân của N là xâu ngược của s

- Chương trình tham khảo

Theo cách 1

program bai7c1;

const maxd=100;

Trang 13

Bài toán 8 Cho số nguyên dương N, hãy sắp xếp các số trong biểu diễn của N

để được số lớn nhất

Dữ liệu vào: Từ tệp văn bản Bai8.inp chỉ một số, là số nguyên N.

Dữ liệu ra: Ghi lên tệp văn bản Bai8.out chỉ một số, là số đã được sắp xếp VD

- Xác định bài toán:

+ Input: Số nguyên dương N

+ Output: Số lớn nhất sắp xếp được trong biểu diễn của số N

- Ý tưởng thuật toán:

Cách 1: Sử dụng mảng một chiều để lưu các số có trong biểu diễn của N(Với Nnhỏ) Để lấy được các số có trong biểu diễn của N, ta dùng phép chia N mod 10,sau mỗi lần chia thì N được gán lại với giá trị mới là N div 10 Quá trình kết thúckhi N=0 Sau đó đưa ra các phần tử của mảng theo thứ tự từ tăng dần Để xác địnhchỉ số cuối của mảng một chiều ta dùng một biến kiểu nguyên d Ban đầu d:=0, sau

đó mỗi lần chia lấy dư N cho 10, ta tăng biến d lên một đơn vị

Cách 2: Sử dụng biến xâu s để lưu N( đọc N dưới dạng xâu) Sau đó ta đưa ra cácphần tử của xâu s theo thứ tự giảm dần

- Chương trình tham khảo

Trang 14

for i:= 1 to length(s) do

if s[i]=j then write(s[i]);

Trang 15

Bài toán 9 Số đối xứng là số mà ta đọc các chữ số của nó từ trước ra sau hay

theo thứ tự ngược lại thì có kết quả như nhau Cho hai số nguyên dương M, N( M<N<=100000000), đếm xem trong đoạn [M, N] có bao nhiêu số đối xứng?

Dữ liệu vào: Từ tệp văn bản Bai9.inp gồm 2 số, là số nguyên M, N Hai số

+ Input: 2 số nguyên dương M, N (M<N<=10000)

+ Output: Số các số đối xứng có trong đoạn [M, N]

- Ý tưởng thuật toán

Cách 1: Với mỗi số trong đoạn [M, N] ta sẽ chuyển nó thành mảng một chiều rồikiểm tra tính đối xứng của các phần tử mảng một chiều đó Việc kiểm tra đối xứngđược thực hiện bằng một chương trình con

Cách 2: Với mỗi số trong đoạn [M, N] ta sẽ chuyển nó thành xâu rồi kiểm tra tínhđối xứng của xâu đó Việc kiểm tra đối xứng cũng được thực hiện bằng mộtchương trình con

- Chương trình tham khảo

while (i<=t div 2) and (c[i]=c[t-i+1]) do inc(i);

if (t>1) and (i>t div 2 ) then dx:=true else dx:=false;

end;

begin

Trang 16

begin i:=1; t:=length(c);

while (i<=t div 2) and (c[i]=c[t-i+1]) do inc(i);

if (t>1) and (i>t div 2 ) then dx:=true else dx:=false;

Trang 17

Còn theo cách 2, ta thấy thuật toán rõ ràng và đơn giản hơn, chương trình cũngngắn hơn.

Bài toán 10 Nhập từ bàn phím số M gồm các chữ số 0 và 1 M là biểu diễn nhị

phân của số nguyên dương N Tìm và đưa ra màn hình số nguyên dương N

Dữ liệu vào: Từ tệp văn bản Bai10.inp chỉ số, là số nguyên M Hai số cách

+ Output: Số nguyên dương N mà biểu diễn nhị phân của nó là M

- Ý tưởng thuật toán:

Cách 1 Tách lần lượt các số trong M, mỗi lần tách được một số ta cộng tích của số

đó với lũy thừa của 2 với số mũ tương ứng vào tổng, đồng thời gán lại giá trị mớicho M M=M div 10 Quá trình trên kết thúc khi M=0 Giá trị của tổng chính là N

Để tính lũy thừa cơ số 2, ta sử dụng chương trình con luythua

Cách 2 Dùng biến xâu s, sau đó chuyển M sang xâu s Gán L:=length(s); Choi:=L-1 tới 0, thực hiện tính tổng:=tổng +j*lũy thừa của 2 với số mũ i Với j là kếtquả của thủ tục val(s[i],j,code) Để tính lũy thừa cơ số 2, ta sử dụng chương trìnhcon luythua

- Chương trình tham khảo

Trang 18

Nhận xét: Theo cách 1, ta thấy vì chưa xác định được số lượng chữ số có trong

M nên khi lập trình ta phải sử dụng câu lệnh while-do

Trang 19

Còn theo cách 2, sau khi đã đổi M sang kiểu dữ liệu xâu thì thông qua hàmlength(s) ta đã xác định được số chữ số trong M nên khi lập trình ta có thể dùngcâu lệnh For-do Tuy nhiên theo cách 2 ta phải dùng thêm thủ tục Val(s[i],j,code).Đây cũng là thủ tục khá hay gặp trong việc giải một số bài toán Với các học sinhtrong đội tuyển HSG thì GV phải trang bị cho HS cả 2 thủ tục này.

Bài toán 11 Cho số nguyên dương N(N<100000000), hãy tìm đoạn đối xứng

liên tiếp dài nhất trong biểu diễn của N

Dữ liệu vào: Từ tệp văn bản Bai11.inp chỉ một số, là số nguyên N.

Dữ liệu ra: Ghi lên tệp văn bản Bai11.out gồm 2 số, là số đối xứng dài nhất

trong biểu diễn của N và độ dài của số đó Hai số cách nhau một dấu cách

- Xác định bài toán:

+ Input: Số nguyên dương N

+ Output: Số đối xứng dài nhất trong biểu diễn của N và độ dài của nó

- Ý tưởng thuật toán:

+ Tạo 1 hàm kiểm tra tính đối xứng của một xâu;

+ Đọc số N dưới dạng xâu s;

+ Duyệt các xâu con của xâu s có độ dài giảm dần từ length(s)1 Nếu xâu conđầu tiên tìm thấy thoả mãn điều kiện thì đưa ra xâu đó và độ dài của nó rồi kết thúcchương trình

- Chương trình tham khảo:

while p<=length(y) div 2 do

if y[p]=y[length(y)-p+1] then inc(p);

if p>=length(y) div 2 then kt:=true else kt:=false;

Trang 20

III Kết quả thực hiện: Sáng kiến kinh nghiệm là kết quả đúc kết của nhiều năm

nghiên cứu và giảng dạy, bồi dưỡng học sinh giỏi Trên thực tế đã đạt được một sốkết quả trong bồi dưỡng học sinh giỏi cấp tỉnh như sau:

IV KẾT LUẬN VÀ KIẾN NGHỊ

Ta thấy việc giải các bài toán trên có thể xử lý bằng các phép toán số họcthường gặp như phép toán chia lấy phần dư ( mod ) và phép chia lấy phần nguyên (div ) Tuy nhiên khi xử lý bằng các phép toán này thì độ trừu tượng tương đối cao

và yêu cầu học sinh phải hiểu bản chất nên chỉ phù hợp với một bộ phận nhỏ họcsinh có năng lực khá trở lên Mặt khác, với N khá lớn thì độ phức tạp càng cao hơn.Nhận thấy các bài toán trên có những điểm chung là:

- Phải xử lý đến từng chữ số ( Kí tự số ) trong N, việc này giống như tham chiếuđến từng phần tử của kiểu dữ liệu xâu- một việc làm rất đơn giản và dễ hiểu đốivới nhiều học sinh;

- Phải xác định N là số có bao nhiêu chữ số, việc này giống như xác định sốlượng ký tự của xâu- một việc làm đơn giản trong kiểu dữ liệu xâu mà học sinh

có thể nhận ra, đó là sử dụng hàm length

Từ những nhận xét trên ta thấy nếu chuyển được N sang dạng xâu thì sẽ rấtthuận tiện khi giải các bài toán trên và việc N là khá lớn cũng không thành vấn đề

Thủ tục để chuyển số N thành xâu s là str(N,s) Thủ tục này làm ẩn đi bản chất của

nó nên làm giảm đi độ phức tạp đối với học sinh mà ý nghĩa và cấu trúc của nó lạirất dễ nhớ, dễ áp dụng

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

TÀI LIỆU CÙNG NGƯỜI DÙNG

TÀI LIỆU LIÊN QUAN

w