Tải bản đầy đủ - 0 (trang)
Dữ liệu ra: Ghi ra tệp SUM.OUT với cấu trúc

Dữ liệu ra: Ghi ra tệp SUM.OUT với cấu trúc

Tải bản đầy đủ - 0trang

End;

Function Cong(a,b : String): String;

Var tong, nho, i, x, y,code : integer;

c, s : String;

Begin

nho:=0; c:='';

While length(a)
a:='0'+a;

While length(b)
b:='0'+b;

For i:=length(a) downto 1 do

Begin

Val(a[i],x,code);

Val(b[i],y,code);

tong:=x + y + nho;

nho:=tong div 10;

Str(tong mod 10,s);

c:=s+c;

End;

If nho>0 then c:='1'+c;

Cong:=c;

End;

Procedure Ghidl;

Var f: text;

Begin

Assign(f,fo); Rewrite(f);

S3:=cong(s1,s2);

Write(f,s3); Close(f);

End;

BEGIN

Docdl;

Ghidl;

END.

Với phương pháp này, chúng ta chỉ tính tốn được với những con số có

khơng q 255 chữ số. Vậy với bài tốn khi những con số có đến 30000 chữ số

khơng thể giải quyết được. Thêm vào đó nếu số lượng chữ số là 255 thì số lượng

phép tốn chuyển đổi từ ký tự thành số và ngược lại là rất nhiều, điều đó làm

tăng thời gian thực hiện của chương trình.

Cách tiếp cận sau đây sẽ giảm độ phức tạp của bài toán:

Chúng ta vẫn sử dụng mảng kiểu số để lưu trữ một số có nhiều chữ số.

Mảng có 3.500 phần tử mỗi phần tử kiểu longint. Mỗi phẩn tử của mảng lưu trữ

-10-



một số nguyên có 9 chữ số. Với phương pháp này ta đã tính tốn được trên hai

số có 30.000 chữ số với thời gian nhanh nhất. Khi cộng (hoặc trừ) hai số có

30.000 chữ số, ta chỉ cần sử sụng 3.100 phép cộng (hoặc phép trừ) và việc cải

tiến thủ tục đọc dữ liệu sẽ giúp thuật tốn hồn tồn loại bỏ được các thao tác

chuyển đổi ký tự thành số

Chương trình:

Program CongSL;

Const fi='SUM.INP';

fo='SUM.OUT';

Var A,B: Array[0..3500] of longint;

i, m,n:Integer;

Procedure Docdl;

Var f:text;

s:String[9];

ch:char;

dua,dub,code:Integer;

Begin

Fillchar(A,sizeof(A),0);

Fillchar(B,sizeof(B),0);

Assign(f,fi);

Reset(f);

Readln(f,m,n);

dua:=m mod 9;

dub:=n mod 9;

m:=m div 9;

n:=n div 9;

If m>n then

Begin

s:='';

For i:=1 to dua do

Begin

read(f,ch);

s:=s+ch;

End;

Val(s,A[1],code);

For i:= 2 to m+1 do

Begin

Read(f,s);

Val(s,A[i],code);

End;

Readln(f);

-11-



s:='';

For i:=1 to dub do

Begin

read(f,ch);

s:=s+ch;

End;

Val(s,B[m-n+1],code);

For i:= m-n+2 to m+1 do

Begin

Read(f,s);

Val(s,B[i],code);

End;

End

Else

Begin

s:='';

For i:=1 to dua do

Begin

read(f,ch);

s:=s+ch;

End;

Val(s,A[n-m+1],code);

For i:= n-m+2 to n+1 do

Begin

Read(f,s);

Val(s,A[i],code);

End;

Readln(f);

s:='';

For i:=1 to dub do

Begin

read(f,ch);

s:=s+ch;

End;

Val(s,B[1],code);

For i:= 2 to n+1 do

Begin

Read(f,s);

Val(s,B[i],code);

End;

End;

-12-



Close(f);

End;

Procedure XL;

Begin

If m>n then n:=m;

For i :=n+1 downto 1 do

Begin

B[i]:=B[i]+A[i];

If B[i] div 1000000000 = 1 then

Begin

B[i]:=B[i] mod 1000000000;

inc(B[i-1]);

End;

End;

End;

Procedure Ghidl;

Var f:text;

Begin

Assign(f,fo);

Rewrite(f);

If B[1]<>0 then Write(f,B[1]);

For i:=2 to n+1 do

If B[i] =0 then Write(f,'000000000')

Else Write(f,B[i]);

Close(f);

End;

BEGIN

Docdl; Xl;

Ghidl;

END.



-13-



Dạng 2: Sử dụng thuật toán chia để trị để giảm độ phức tạp của bài toán

Bài 1: Chọn dãy số

Một lần, Cuội và Bờm đang chơi với nhau. Cuội vẽ lên đất một dãy gồm

N ô vuông liên tiếp nhau và viết vào mỗi ô một số nguyên dương. Cuội thách

Bờm hãy chọn một dãy các ô liên tiếp nhau sao cho tổng các số trong dãy các ô

đã chọn bằng tổng các số trong các ơ còn lại.

u cầu: Hãy tính xem Bờm có bao nhiêu cách chọn thỏa mãn yêu cầu

mà Cuội đã đưa ra?

Dữ liệu vào: Tệp văn bản CHONDAY.INP

+ Dòng đầu ghi số nguyên N (2<=N<=105)

+ Dòng thứ hai ghi N số nguyên cách nhau một dấu cách. Các số trên

dòng này không vượt quá 1000.

Dữ liệu ra: Tệp văn bản CHONDAY.OUT chỉ ghi duy nhất một số

nguyên là số cách mà Bờm có thể chọn.

Ví dụ:

CHONDAY.INP

CHONDAY.OUT

4

2

4121

Lời giải:

Gọi A là dãy gồm N phần tử đã cho

Bài toán quy về đếm xem có bao nhiêu đoạn liên tục từ vị trí i đến j (1 ≤

i
trong dãy A.

Cách 1: Thuật toán tầm thường

Gọi T là tổng các số trong dãy. Nếu T lẻ bài tốn có nghiệm bằng 0.

Ngược lại gán S = T div 2.

Sử dụng thuật toán duyệt kết hợp với việc lưu trữ tổng các số trên mảng

một chiều ta dễ dàng giải bài toán với độ phức tạp O(n2).

Gọi Bi là tổng các phần tử từ 1 đến i trong A (i=0..n và B 0=0). Như vậy

tổng các phần tử trong A từ i đến j (i ≤ j) = Bj – Bi-1.

Thuật toán tạo mảng B nhu sau:

B[0]:=0;

For i:=1 to n do B[i]:=A[i]+B[i-1];

Thuật toán duyệt sẽ như sau:

dem:=0;

For i:=1 to n do

For j:=i to n do

If B[j]-B[i-1] = S then Inc(dem);

-14-



Cách 2: Duyệt kết hợp tìm kiếm nhị phân để đưa độ phức tạp về O(nlgn)

Về cấu trúc dữ liệu tương tự cách 1. Ta để ý rằng vì B i là tổng các phần tử

dương trong A từ 1 đến i nên Bi > Bi-1 hay nói cách khác dãy các phần tử trong B

tăng dần.

Gọi j là phần tử cuối của dãy cần tìm phần tử i trước j sao cho B[j]-B[i-1]

bằng S. Để tìm i ta dùng thuật tốn tìm kiếm nhị phân vì dãy B là dãy tăng dần.

Điều đó cho phép giảm độ phức tạp xuống còn O(nlgn)

Chương trình

Program Chondayso;

Const

fi

= 'CHONDAY.INP';

fo

= 'CHONDAY.OUT';

maxn=100001;

Var

A:array[0..maxn] of longint;

n,kq,t:longint;

Procedure Docdl;

Var f:text;

i, x:longint;

Begin

Fillchar(a,sizeof(a),0);

kq:=0;

Assign(f,fi); reset(f);

Readln(f,n);

For i:=1 to n do

Begin

Read(f,x);

a[i]:=a[i-1]+x;

End;

Close(f);

End;

Procedure Tim(d,c,v:longint);

Var m,sum:longint;

Begin

If d>c then exit;

m:=(d+c) div 2;

sum:=a[v]-a[m-1];

If sum = t then inc(kq)

Else

If sum < t then Tim(d,m-1,v) else Tim(m+1,c,v);

End;

Procedure Ghi;

Var f:text;

-15-



Begin

Assign(f,fo); Rewrite(f);

Writeln(f,kq);

Close(f);

End;

Procedure Xuli;

Var i:longint;

Begin

If odd(a[n]) then

Begin

kq:=0;

ghi;

exit;

End;

t:=a[n] div 2;

for i:=n downto 1 do Tim(1,i, i);

Ghi;

End;

BEGIN

Doc;

Xuli;

END.

Bài 2: Hiệu

Cho mảng số nguyên A[1..n], cần tìm Hieu(A[1..n]) = A[j]-A[i] đạt giá trị

lớn nhất mà (1 ≤ i ≤ j ≤ n).

Input: Tệp văn bản HIEU.INP

+ Dòng đầu ghi số N (N ≤ 10000)

+ Dòng thứ hai ghi n số nguyên cách nhau một dấu cách ( ≤ 1000);

Output: Tệp văn bản HIEU.OUT ghi số ngun HIEU tìm được.

Ví dụ:

HIEU.INP

HIEU.OUT

6

6

425817

Lời giải

Cách 1: Duyệt thử với tất cả các cặp chỉ số (i,j) với độ phức tạp O(n2)

MaxHieu:=0;

For i:=1 to n do

For j:=i to n do

If a[j]-a[i] > MaxHieu then MaxHieu:= A[j]-A[i];

-16-



Cách 2: Dùng phương pháp chia để trị chia mảng A thành 2 mảng con

a[1..k] và A[k..n] trong đó k = n div 2. Độ phức tạp sẽ giảm xuống còn O(nLgn)

Ta có: Hieu(A[1..n]) =Max(Hieu(A[k..n])-Min(Hieu(A[1..k]));

Chương trình

Program Hieu;

Const

fi

= 'Hieu.inp';

fo = 'Hieu.out';

maxn= 10000;

Var

A:array[1..maxn] of longint;

n:longint;

maxd,mind,maxHieu:longint;

Procedure Docdl;

Var f:text;

i:longint;

Begin

Assign(f,fi); reset(f);

Readln(f,n);

For i:=1 to n do read(f,a[i]);

Close(f);

End;

Procedure Tim(l,r:longint; var maxhieu,maxd, mind:longint);

Var maxd1, mind1, maxhieu1, maxd2, mind2, maxhieu2, mid:longint;

Begin

If l=r then

Begin

maxd:=a[r];

mind:=a[r];

maxhieu:=0;

End

Else

Begin

mid:=(l+r) div 2;

Tim(l,mid,maxhieu1,maxd1,mind1);

Tim(mid+1,r,maxhieu2,maxd2,mind2);

maxhieu:=maxd2-mind1;

If maxhieu
If maxhieu
If maxd1>maxd2 then maxd:=maxd1 else maxd:=maxd2;

If mind1
End;

End;



-17-



Procedure ghi;

var f:text;

Begin

assign(f,fo); rewrite(f);

writeln(f,maxHieu);

close(f);

End;

BEGIN

Docdl;

Tim(1,n,maxhieu,maxd, mind);

ghi;

END.

3. Đánh giá kết quả thực nghiệm.

Sau khi áp dụng đề tài này vào trong giảng dạy và bồi dưỡng cho học

sinh giỏi tin lớp 11 bước đầu đã thu được kết quả đáng kể.

- Trước khi áp dụng sáng kiến kinh nghiệm kết quả khảo sát cho các học

sinh giỏi khối 11 là:

+ Mức điểm giỏi: 0%

+ Mức điểm khá: 30%

+ Mức điểm TB: 55%

+ Mức điểm yếu: 15%

- Sau khi áp dụng sáng kiến kinh nghiệm kết quả khảo sát cho các học

sinh giỏi khối 11 là:

+ Mức điểm yếu giảm còn là:

0 %.

+ Mức điểm trung bình giảm còn là: 35%.

+ Mức điểm khá là:

57%

+ Mức điểm giỏi tăng lên là:

8%

Kết quả kỳ thi học sinh giỏi Tỉnh khối 11 đạt 02 giải KK



-18-



III. KẾT LUẬN

1. Ý nghĩa của đề tài, sáng kiến:

Đề tài này chỉ là một chuyên đề nhỏ nhằm giới thiệu đến học sinh phương

pháp và một số kỹ năng phân tích bài tốn tin học thể hiện qua một số ví dụ từ

đơn giản đến nâng cao giúp học sinh bước đầu tiếp cận với bài tốn tin học, biết

cách phân tích bài tốn theo từng bước một để tìm ra cách giải và kỹ năng sử

dụng ngơn ngữ lập trình để cài đặt chương trình.

Tuy nhiên, do vẫn còn những hạn chế về trình độ hiểu biết chun mơn,

thời gian thực hiện đề tài còn hạn hẹp. Do đó, trong đề tài chắc chắn sẽ khơng

tránh được những thiếu sót, rất mong sự đóng góp ý kiến của đồng nghiệp để đề

tài được hoàn thiện hơn.

2. Kiến nghị, đề xuất:

Là một giáo viên đang giảng dạy tại trường THPT tôi xin kiến nghị: Các

cơ quan ban ngành, nhà trường luôn tạo điều kiện về cơ sở vật chất, tinh thần

cho những giáo viên giảng dạy và bồi dưỡng học sinh giỏi. Đồng thời tạo điều

kiện cho GV được đi tập huấn để nâng cao trình độ. Tơi mong rằng với kiến

nghị này, các cơ quan ban ngành luôn tạo điều kiện và giúp đỡ.



-19-



IV. TÀI LIỆU THAM KHẢO

- Sáng tạo trong thuật tốn và lập trình – Nguyễn Xn Huy

- Tài liệu chuyên tin quyển 1 – Hồ Sỹ Đàm, Đỗ Đức Đơng, Lê Minh

Hồng, Nguyễn Thanh Hùng;

- Tài liệu tập huấn bồi dưỡng học sinh giỏi môn tin học ở trường THPT

của Sở GD-ĐT Quảng Bình

- Sưu tầm trên Internet.



-20-



Tài liệu bạn tìm kiếm đã sẵn sàng tải về

Dữ liệu ra: Ghi ra tệp SUM.OUT với cấu trúc

Tải bản đầy đủ ngay(0 tr)

×