VIETBOOK
Trang 1
Olimpic lập trình
I.1. Các bài toán Olimpic
Trong Olimpic Tin học Mat-Xcơ-va, ngời ta ra cho học sinh phổ thông một số nhóm bài toán. Số
các bài toán dao động từ 5 đến 11 bài. Các bài toán luôn luôn có mức điểm khác nhau, xếp theo trật tự dễ
dần và khi tính điểm chỉ lấy 3 lời giải tốt nhất. Các thí sinh đợc báo trớc tất cả những điều này. Những bài
đầu tiên có thể là khá khó, còn những bài cuối cùng mang tính chất khích lệ. Kỳ thi kéo dài 4 giờ, lời giải có
thể viết trên bất kỳ ngôn ngữ nào. Trớc khi giải nhất thiết phải viết thuật giải bằng lời. Điều này làm cho
việc đọc chơng trình dễ dàng. Tính rõ ràng của thuật toán, việc tiết kiệm số các thao tác, tính ngắn gọn của
chơng trình đợc cho thêm điểm, còn việc lập trình sử dụng mảng thừa và có lỗi bị hạ thấp điểm.
Trong phát biểu các bài toán và trình bày thuật toán qui ớc dùng các ký hiệu sau đây: Các mảng A
1
,
A
2
, A
n
đợc ký hiệu là A[1:n] với A[i] là các phần tử của nó. Cũng nh vậy kí hiệu A[1:m,1:n] và A[i,j]
cho mảng hai chiều v.v
Số lợng các phần tử của mảng và chỉ số các phần tử của mảng là các số tự nhiên, còn lại là các số
thực ( nghĩa là số với dấu phẩy động), nếu không có ớc định nào khác.
Nếu ở đầu bài nói rằng Cho mảng A[1:n] thì học sinh cần viết chơng trình tự nhập số n, tạo mảng
n phần tử và nhập giá trị của các phần tử này. Nếu trong ngôn ngữ ( Ví dụ ngôn ngữ Pascal ) không có
mảng động, thì cần chấp nhận n<100 và lập mảng 100 phần tử, nhng chỉ nhập giá trị cho n phần tử cho
trớc. Cũng nh thế đối với mảng 2 chiều và nhiều chiều hơn. Tuy nhiên thí sinh đợc phép giả thiết phần
chơng trình đợc viết là một phần của chơng trình bao nó trong đó mảng đã đợc tạo lập và các phần tử
của mảng đã đợc nạp từ trớc. Nhng thí sinh cần nói rõ điều này. Tất cả các câu trả lời đều phải đợc đa
ra màn hình hoặc máy in. Một lần nữa cần nhấn mạnh rằng lời giải phải là chơng trình, không thể thay
chơng trình bằng bất cứ lập luận nào.
Olimpic 80
Các thí sinh đợc giao 11 bài chia làm 3 nhóm. Các nhóm đợc sắp xếp theo thứ tự dễ dần, trong
một nhóm các bài toán đợc tính điểm nh nhau. Từ mỗi nhóm lấy không quá một bài để tính điểm thi.
80.1.1 . Các số nguyên tố không vợt quá M
Hãy in ra tất cả các số nguyên tố không vợt quá số M cho trớc.
80.1.2. Hoán vị :
Cho trớc mảng A[1:n], chứa các số khác nhau từng đôi một. Hãy in ra toàn thể các hoán vị của các
số đó.
80.1.3 . Nâng lên luỹ thừa nhanh :
Nạp số thực A và số tự nhiên k. Hãy tính và in ra A
k
với điều kiện sau đây: Không đợc sử dụng
phép tính nâng lên luỹ thừa, k đủ lớn để không thể thực hiện k phép nhân.
80.1.4. Các phép tính số học :
Trong biểu thức (((( 1 ? 2 ) ? 3 ) ? 4 ) ? 5 ) ? 6 . Hãy thay các dấu ? bằng một trong các phép tính số
học +, -, *, / sao cho kết quả tính đợc là 35( khi chia phần d đợc bỏ đi)
Chỉ cần tìm một lời giải.
80.2.1 . Tìm kiếm các phần tử bằng nhau :
Cho mảng A[1:2,1:15], có chứa đúng hai phần tử bằng nhau. Hãy in ra chỉ số của hai phần tử đó.
PDF processed with CutePDF evaluation edition www.CutePDF.comPDF processed with CutePDF evaluation edition www.CutePDF.com
CM Soft 70 NCT F2 Q10
CM Soft 70 NCT F2 Q10
PDF processed with CutePDF evaluation edition www.CutePDF.comPDF processed with CutePDF evaluation edition www.CutePDF.com
VIETBOOK
Trang 2
80.2.2 Tổng bình phơng
Có thể viết số tự nhiên M cho trớc dới dạng tổng các bình phơng của hai số tự nhiên hay không ?
Hãy viết chơng trình giải bài toán này.
80.2.3 Các số khác nhau
Cho trớc mảng số A[1:m]. Tìm và in ra số các số khác nhau trong mảng này.
Ví dụ trong mảng 5,7,5 có hai số khác nhau ( 5 và 7 ).
80.3.1 Số có tổng các chữ số cho trớc
Viết chơng trình in ra tất cả các số ở hệ cơ số 10 có ba chữ số mà tổng các chữ số bằng một số tự
nhiên cho trớc.
80.3.2 M + 1 ở hệ nhị phân
Số nguyên không âm M đợc cho bởi mảng các chữ số nhị phân là a
0
, a
1
, a
2
, a
n-1
: M = a
n-
1
.2
n-1
+ + a
1
.2 + a
0
Trong đó a
i
bằng 0 hoặc 1 ( i = 0,1,2, n-1 ) Hãy viết mảng các chữ số nhị phân của M+1.
80.3.3 Cực đại của các cực tiểu :
Trong mảng X[1:m,1:n] tất cả các số khác nhau. ở mỗi dòng tìm một phần tử nhỏ nhất, sau đó trong
số này chọn ra số lớn nhất. Hãy in ra chỉ số của dòng của mảng X chứa số đã đợc chọn.
80.3.4. Hoán vị 0, 1, 2.
Trong mảng X[1:n] mỗi phần tử bằng 0, 1 hoặc 2. Hoán vị các phần tử của mảng, sao cho đầu mảng chứa
các số 0, sau đó là các số 1 và cuối mảng là các số 2 ( không đợc dùng mảng phụ ).
Olimpic 81
Các thí sinh đợc giao 5 bài toán sắp xếp theo thứ tự dễ dần. Chỉ đợc tính điểm 3 bài.
81.1 Hàm số :
Hàm số f(n) với các số n nguyên không âm đợc xác định nh sau :
f(0) = 0 , f(1) = 1 , f(2n)
= f(n) , f(2n+1) = f(n) + f(n+1).
Với N cho trớc xác định và in ra f(N).
Điều kiện bắt buộc
: N đủ lớn để không thể mảng gồm N phần tử ( hoặc khai báo mảng có chiều dài tăng
theo N ).
81.2. Cặp bốn số .
Hãy nạp số n và lấp đầy mảng hai chiều kích thớc n
2
bằng các số 1, 2, 3, theo hình xoắn ốc (
hình vẽ ).
81.3. Các số lập từ các chữ số khác nhau:
In ra tất cả các số tự nhiên có 4 chữ số mà biểu diễn ở hệ thập phân của chúng không có hai chữ số
nào giống nhau.
81.5 Loạt các số không.
CM Soft 70 NCT F2 Q10
CM Soft 70 NCT F2 Q10
VIETBOOK
Trang 3
Cho mảng số A[1:n] . Hãy tìm độ dài của dãy con lớn nhất gồm các phần tử liên tiếp toàn số không.
Olimpic 82
Các thí sinh đợc giao 6 bài toán theo trật tự dễ dần. Chỉ tính điểm 3 bài.
82.1 Hình chữ nhật .
Trên giấy kẻ ô khổ 100 x 100 ô, có vẽ một số hình chữ nhật. Mỗi hình chữ nhật đợc tạo từ các ô
nguyên vẹn, các hình khác nhau không chồng lên nhau và không tiếp xúc nhau.
( hình 1.2 )
Cho mảng kích thớc 100 x 100, trong đó phần tử A[i,j] = 1 nếu ô [i,j] thuộc một hình chữ nhật nào
đó, còn A[i,j] = 0 trong trờng hợp ngợc lại.
Hãy viết chơng trình tính và in ra số các hình chữ nhật.
82.2 Các phân số đợc sắp thứ tự
In theo trật tự tăng dần tất cả các phân số tối giản trong khoảng (0, 1) có các mẫu số không vợt quá
7.
82.3 Tổng theo tập con :
Cho trớc mảng số nguyên A[1: n] và số M . Tìm tập hợp các phần tử A[i
1
], A[i
2
], A[i
k
]
1<=i
1
<=i
2
<= <=i
k
<= <=i
n
sao cho A[i
1
] + A[i
2
] + +A[i
k
] = M
Giả thiết rằng tập hợp này tồn tại.
82.4 Những chữ số không ở cuối .
Cho trớc mảng một chiều. Hãy viết lại mảng sao cho tất cả các phần tử khác không nằm ở đầu
mảng, các phẩn tử bằng không ở cuối mảng và vẫn giữ nguyên trật tự trớc sau của các phần tử, không đợc
thiết lập một mảng mới
82.5 Điểm yên ngựa :
Cho trớc mảng số A[1:m,1:n]. Ta gọi một phần tử của mảng này là điểm yên ngựa nếu nó đồng thời
là phần tử nhỏ nhất trên dòng chứa nó và lớn nhất trên cột chứa nó.
Hãy in số thứ tự của dòng và cột của một điểm yên ngựa nào đó và in ra số không nếu không có
điểm nh vậy.
82.6 Từ trong một văn bản :
Cho trớc hai mảng số nguyên X[1:n], Y[1:k]. Có thể lựa chọn đợc hay không trong mảng thứ nhất
k phần tử liền nhau
X[i+1], X[i+2], X[i+k] , sao cho
X[i+1] = Y[1], X[i+2] = Y[2], , X[i+k] = Y[k]. ?
Hãy viết chơng trình giải bài toán này và in ra câu trả lời Có hay Không.
CM Soft 70 NCT F2 Q10
CM Soft 70 NCT F2 Q10
VIETBOOK
Trang 4
Olimpic 83
Các thí sinh đợc giao 5 bài theo trật tự dễ dần. Chỉ có 3 bài đợc tính điểm.
83.1. Đảo bit :
Số nguyên m đợc viết trong hệ cơ số 2 theo trật tự ngợc lại. Số nhận đợc viết trong hệ thập phân,
đợc coi là giá trị của hàm B(m).
Hãy in giá trị B(m) với m=512,513,514, 1023.
Thí dụ, ba giá trị đầu tiên cần in là :
1; 513; 257;
83.2. Hình tam giác và điểm :
Cho trớc trong hệ toạ độ vuông góc các điểm (X
1
,Y
1
), (X
2
,Y
2
),(X
3
,Y
3
) là đỉnh của một tam giác và
X,Y là toạ độ của một điểm. Hãy xác định xem điểm đó có nằm trong tam giác hay không ( bỏ qua sai số
của phép tính)
83.3. Mê cung :
Du khách có thể ra khỏi mê cung đợc hay không ? Nếu có thể hãy in đờng đi từ lối ra đến vị trí ban
đầu của du khách. Mê cung đợc cho bởi mảng A kích thớc 40 x 40, trong đó :
A[k,m] = 0 , nếu ô [k,m] đi qua đợc (ô thông)
A[k,m] = 1 , nếu ô [k,m] không đi qua đợc (ô cấm).
Vị trí ban đầu của du khách đợc cho ở ô thông [i,j]. Du khách có thể chuyển từ một ô thông này đến ô
thông khác nếu chúng có chung cạnh. Du khách đi ra khỏi mê cung nếu rơi vào ô biên giới ( tức là ô [k,m],
trong đó k hoặc m bằng 1 hoặc 40 ).
83.4. Cái ca :
Cho trớc mảng X[1:m]. Hãy tìm độ dài lớn nhất của dãy liên tiếp các số hình ca (có răng
hớng lên trên )
X[p+1] < X[p+2] > X[p+3]< >X[p+k].
83.5. Rút gọn phân số :
Cho trớc các số tự nhiên m và n . Hãy tìm các số m1, n1 nguyên tố cùng nhau và m/n = m1/n1.
Olimpic 84
Các thí sinh đợc giao 7 bài theo trật tự dễ dần. Chỉ tính điểm 3 bài.
84.1 Nghịch thế.
Giả sử P = (p
1
, ,p
n
) là một hoán vị của các số 1,2, ,n. Ngời ta gọi dãy T = (t
1
t
n
) là bảng nghịch
thế của phép hoán vị P, nếu t
i
là số lợng các phần tử của phép hoán vị P, nằm ở phía trái i và lớn hơn i. Ví
dụ, đối với phép hoán vị P = (5,9,1,8,2,6,4,7,3) của các số 1,2, ,9 thì bảng nghịch thế sẽ là T =
(2,3,6,4,0,2,2,1,0).
Hãy viết chơng trình sao cho theo bảng nghịch thế cho trớc phục hồi đợc hoán vị ban đầu.
84.2 Con đờng:
Cho trớc các số tự nhiên n>=2 và mảng các số thực A[1 : m,1: m,1: n-1]. Hãy tìm giá trị nhỏ nhất
của tổng [ R= A]i
1
,i
2
,1]+ A[i
2
,i
3
,2] + + A[i
n-1
,i
n
,i
n-1
] với các bộ số nguyên tố có thể có 1<= i
1
,
i
2
in<=m.
CM Soft 70 NCT F2 Q10
CM Soft 70 NCT F2 Q10
VIETBOOK
Trang 5
Chú ý
: Giá trị các số m, n khoảng vài chục, vì thế không chấp nhận lời giải với số thao tác m
n
84.3. Những số hoàn thiện.
Số tự nhiên đợc gọi là hoàn thiện, nếu nó bằng tổng tất cả các ớc số của nó, kể cả 1. Hãy in tất cả
các số hoàn thiện nhỏ hơn số N cho trớc.
84.4 Chu kì của phân số :
Nạp các số tự nhiên m và n rồi in chu kì của phân số m/n.
Ví dụ
: đối với phân số 1/7 sẽ có chu kì ( 142857 ). Nếu phân số hữu hạn thì chu kì bằng 0.
84.5 Trộn các mảng :
Cho trớc hai số m, n và hai mảng đã đợc sắp A[1]<=A[2]<= <=A[m] ;
B[1]<=B[2]<= <=B[n]. Hãy trộn hai mảng trên để có mảng cũng đợc sắp thứ tự C[1]<=C[2]<=
<=C[m+n].
Chỉ dẫn
: Chú ý đến số phép tính của chơng trình khi m và n khá lớn.
84.6 Lịch :
Cho trớc 3 số A, B, C biểu thị ngày, tháng, năm. Hãy tìm số thứ tự N của ngày trong năm tính từ
ngày đầu của năm ấy.
Chỉ dẫn
: Năm nhuận là năm chia hết cho 400 và những năm chia hết cho 4 nhng không chia hết
cho 100.
84.7 . Những hình vuông :
Cho trớc mảng A[1:m,1:n] mỗi phần tử của nó bằng 0, 1,5 hoặc 11. Hãy tính số lợng các bộ bốn
A[i,j], A[i+1,j], A[i,j+1], A[i+1,j+1] trong đó các phần tử đều khác nhau.
Olimpic 85
Các thí sinh đợc giao 7 bài, theo trật tự dễ dần. Chỉ tính vào kết quả 3 bài.
85.1 Dạng tổng :
In tất cả các cách viết số tự nhiên N dới dạng tổng các số tự nhiên. Việc đổi chỗ các số hạng không
đợc coi là một cách mới.
85.2. Các phần tử bằng nhau :
Cho trớc mảng số nguyên A[1:m, 1:n]. Mỗi dòng của mảng đợc xếp theo thứ tự tăng dần, nghĩa là
A[i,1] <= A[i,2] với tất cả các
i = 1,2,3, ,m.
Hãy tìm và in số có mặt ở tất cả các dòng và in ra " Không" nếu số nh vậy không có.
85.3. Số không thể tách đợc .
Cho trớc mảng số tự nhiên P[1:n]. Hãy tìm số tự nhiên nhỏ nhất không thể viết dới dạng tổng các
phần tử thuộc mảng P. Tổng có thể chỉ gồm một số hạng, nhng mỗi phần tử của mảng chỉ đợc tham gia
vào đó một lần.
85.4. Tứ diện.
Trên các mặt của hai tứ diện đều bằng nhau M và N có viết các số M
1
, M
2
, M
3
, M
4
và N
1
, N
2
, N
3
, N
4
theo trật tự đã chỉ ra trên hình 1.3
hình 1.3
CM Soft 70 NCT F2 Q10
CM Soft 70 NCT F2 Q10
VIETBOOK
Trang 6
Có thể đặt khít các tứ diện sao cho trên các mặt trùng nhau có các số nh nhau hay không ?
Hãy in Có hoặc Không tơng ứng với các trả lời tìm đợc.
85.5. Mốt.
Tìm số xuất hiện nhiều lần nhất trong mảng số nguyên A[1:n]. Nếu có vài số nh vậy thì lấy một
số.
85.6. Hệ đếm.
Trong mảng M[1:9] có viết các chữ số của một số tự nhiên trong hệ đếm I. ( M[1] là số hàng đơn
vị, v.v). In các chữ số này trong hệ đếm J, bắt đầu từ hàng đơn vị. Các số I, J không vợt quá 10.
85.7. Đờng chéo phụ.
Tìm tổng các phần tử A(i,j) của mảng A[1:m,1:n], có hiệu các chỉ số là i-j=k.
Chú ý
: k có thể là số âm.
Olimpic 86
Thí sinh đợc giao 5 bài theo trật tự dễ dần. Chỉ tính điểm 3 bài.
86.1. Không lặp 3 lần .
Hãy tìm dãy 50 số 0 và số 1, trong đó không có dãy con lặp lại 3 lần liên tục.
Hãy in Không nếu dãy nh không tồn tại.
Vĩ dụ
: trong dãy tìm đợc không chứa các đoạn 000 hoặc 101010, hoặc 101101101.
86.2. Bài Pô-Cơ.
Cho mảng gồm 5 số, trong đó :
- Nếu 5 số giống nhau, thì in số 1, nếu không
- Nếu có 4 số giống nhau, thì in số 2, nếu không
- Nếu có 3 số giống nhau và còn 2 số còn lại cũng giống nhau, thì in số 3, nếu không
- Nếu chỉ có 3 số giống nhau, thì in số 4, nếu không
- Nếu có 1 cặp số giống nhau thì in số 6, nếu không thì in số 7.
86.3. Cái trống.
Theo hình tròn viết 12 số a
1
, , a
12
. Nếu viết chúng từ số hiệu k, thì nhận đợc vec tơ x
k
= (a
k
,
a
k+1
, , a
k+11
)
Trong đó a
13
đợc hiểu là a
1
, a
14
đợc hiểu là a
2
Vec tơ x
k
đợc coi là nhỏ hơn x
p
, nếu cặp số đầu tiên không bằng nhau sẽ là a
k+i
< a
p+i
86.4. Tính đơn điệu kép.
Mảng số A[1:m,1:n] đợc sắp theo dòng nh sau :
A[i,1]<=A[i,2]<= với mọi i =1,2,3 m
A[1,j]<=A[2,j]<= với mọi j =1,2,3 n
Tìm phần tử của mảng bằng số x cho trớc và in ra chỉ số của nó. In Không nếu phần tử nh vậy không có.
Điều kiện bắt buộc
: lời giải cần có độ phức tạp m+n ( chứ không phải m*n).
CM Soft 70 NCT F2 Q10
CM Soft 70 NCT F2 Q10
VIETBOOK
Trang 7
86.5. Làng trung tâm .
Có k làng. Nếu ở làng i đặt trạm cấp cứu, thì xe cấp cứu đi đến làng j theo tín hiệu gọi cần thời gian :
A[i,i] + A[i,j] [ 1<=i, j<=k, i = j ]
Tìm số hiệu làng i để đặt trạm cấp cứu sao cho từ đó đi tới làng xa nhất ( về thời gian ) sẽ mất thời gian
ngắn nhất. Mảng A[1:k,1:k] cho trớc, trong đó tất cả phần tử A[i,j]>0 và phần tử A[i,j] có thể không bằng
phần tử A[j,i].
Olimpic 87
Thí sinh đợc giao 5 bài theo trật tự dễ dần. Chỉ tính điểm 3 bài.
87.1. Ba lô :
Từ n vật chọn ra các vật sao cho tổng khối lợng của chúng nhỏ hơn 30 kg, còn giá trị còn lại là lớn
nhất. In tổng giá trị của các vật thể đã đợc chọn.
Cụ thể là cho 2 mảng số dơng A[1:n] và B[1;n]. Chọn các chỉ số khác nhau đôi một i
1
,i
2
, i
k
sao
cho
A[i
1
] + A[i
2
] + + A[i
k
] <30
B[i
1
] + B[i
2
] + + B[i
k
] = m là lớn nhất.
Chỉ cần in giá trị m
Chú ý
: Có thể giả thiết rằng các vật thể đã đợc sắp xếp theo trật tự tăng dần hoặc giảm dần theo khối
lợng A[i], theo giá trị B[i], theo giá trị A[i]/B[i] hoặc một dấu hiệu bất kỳ nào khác.
87.2 Nửa bội.
Tập hợp số A cho trớc với điều kiện :
a) a A
b) Nếu k A, thì 2*k +1 A và 3*k +1 A và ngoài ra tập hợp A không chứa các số nào khác.
In n số đầu tiên ( n<100 ) của tập hợp A theo trật tự tăng dần.
Ví dụ
: Các phần tử đầu của dãy cần in : 1,3,4,7,9,10,13,15,19
87.3. Tổng các lập phơng.
Có bao nhiêu phơng pháp viết số tự nhiên N cho trớc thành tổng các lập phơng của hai số tự
nhiên :
N = i
3
+ j
3
Sự hoán vị các số hạng không đợc tính, không đợc sử dụng phép tính nâng lên luỹ thừa 1/3.
87.4. Lật ngợc.
Cho trớc mảng số A[1:n]. Tìm đoạn đối xứng dài nhất của mảng A đó ( số đầu tiên bằng số cuối
cùng, số thứ hai bằng số đứng trớc số cuối cùng ). Hãy in độ dài của đoạn này.
87.5. Chỉ số thứ tự.
Cho trớc mảng số A[1:n]. Hãy tìm và in hoán vị i
1
, i
2
, ,in của số 1, 2, 3, ,n sao cho
A[i
1
]<=A[i
2
]<= <=A[i
n
].
Olimpic 88
Thí sinh đợc giao 5 bài theo trật tự dễ dần. Chỉ tính điểm 3 bài.
CM Soft 70 NCT F2 Q10
CM Soft 70 NCT F2 Q10
VIETBOOK
Trang 8
88.1. Lớn bên phải.
Cho trớc mảng số dơng A[1:n]. Đối với mọi phần tử A[i] hãy chọn trong số các phần tử về bên
phải A[i] và lớn hơn A[i] chỉ số nhỏ nhất j rồi thay giá trị A[i] bằng A[j].
Nếu không tìm đợc phần tử A[j] nh vậy thì thay thế A[i] bằng 0. In lại mảng đã nhận đợc.
Điều kiện bắt buộc
: số phép tính ở lời giải cần phải là O(n) chứ không phải là O(n
2
). Có thể sử dụng mảng
phụ.
Giải thích :
Ví dụ mảng 2,9,8,5,9,3,4,5,2, sai khi thay trở thành mảng 9,0,9,9,0,4,5,0,0.
88.2. Đa thức.
Tính các hệ số a[0], a[1], , a[n-1] của đa thức
P(x) = a[0] + a[1]*x + a[2]*x
2
+ + a[n-1]*x
n-1
+ x
n
Với các nghiệm thực cho trớc x[1], x[2], x[n].
Gợi ý
: Theo định lý Bơ Du :
P(x) = (x - x[1]) * (x - x[2]) * * (x - x[n]).
88.3. Ước số nguyên tố :
Cho trớc số tự nhiên N. Hãy tìm tất cả các ớc số nguyên tố của nó.
88.4. Hàng mua buôn.
Một đôi tất ngắn giá 1,05 rúp, một bó tất ( 12 đôi ) giá 10,25 rúp, còn 1 hộp ( 12 bó ) giá 114 rúp.
Lập chơng trình sao cho ứng với n đôi tất cần mua, tính số n
1
hộp tất, n
2
bó tất, n
3
đôi tất mà ngời đó cần
mua cho đỡ tốn tiền nhất .
Giải thích
: Thay việc mua 11 đôi tất cần mua bằng mua một bó tất đỡ tốn tiền hơn.
88.5 Đa về bằng 0 :
Trong một mảng 2 chiều cho trớc A[1:n, 1:n], hãy thay thế tất cả các phần tử ở hàng hoặc cột có
chữ số 0 bằng 0.
Điều kiện :
Có thể đa vào mảng phụ một chiều nhng không đợc dùng mảng phụ 2 chiều.
CM Soft 70 NCT F2 Q10
CM Soft 70 NCT F2 Q10
VIETBOOK
Trang 9
Phần hai - Thuật toán
Trong phần này trình bày các thuật giải. Với một số bài thuật giải đợc trình bày có thể dễ dàng
chuyển sang chơng trình, với một số bài khác đó mới chỉ là ý tởng giải, có lúc là chú giải, giải thích
chơng trình. Nhng trong mọi trờng hợp chúng tôi cố gắng làm cho việc đọc chơng trình đợc dễ dàng,
trình bày phơng pháp lập trình đúng đợc ghi nhớ. Số lợng các phép toán của thuật giải chính xác đến
một bội hằng.
ôlimpic 80
80.1.1. Những số nguyên tố đến M :
Để tăng tốc độ tính toán ta nên dùng một mảng chứa những số nguyên tố thu đợc và kiểm tra xem
số đang xét chia hết của phần tử đã nạp trong bảng hay cha. Số chẵn hiển nhiên không phải xét. Bảng cần
có kích thớc tối đa là phần tử. Vì thế những bảng 1000 phần tử sẽ đủ để chứa những số nguyên tố đến
4.000.000.
80.1.2. Hoán vị :
Đặc trng của bài toán bài là ở chỗ, cần thu đợc tất cả các hoán vị. Điều này sẽ làm giảm đáng kể
số lợng thao tác so với bài toán chọn toàn bộ. Tuy nhiên thử tởng tợng là toàn bộ các hoán vị của các số
1,2,3, m đợc sắp xếp theo trật tự từ điển để tìm cách đa vào một hoán vị xây dựng các hoán vị tiếp
theo bằng cách, xuất phát từ hoán vị đầu tiên xây dựng các hoán vị tiếp theo. Cụ thể là với mỗi hoán vị P = (
p1,p2, ,pm ) của các số 1,2, ,m, chúng ta cũng làm phép đổi chỗ nh vậy (A(p1),A(p2), ,A(pm))
của những số A cho trớc.
Để xây dựng trực tiếp hoán vị tiếp theo hoán vị cho trớc P = ( p
1
, p
2
, ,p
m
) chúng ta duyệt các số
p
1
, p
2
, ,p
m
từ phía cuối và dừng lại khi gặp đợc thành phần p
1
đầu tiên nhỏ hơn thành phần thành phần
đứng bên phải nó ( p
1
< p
i+1
). Nếu không có thành phần nh vậy, thì hoán vị P có dạng (m,m-1, ,1) nghĩa là
hoán vị cuối cùng. Rõ ràng rằng các thành phần p
i+1
> p
i+2
> > p
m
tạo các dãy giảm dần. Chúng ta tìm
trong số đó thành phần đầu tiên p
j
( tính từ cuối ), lớn hơn p
i
, và đổi chỗ chúng cho nhau.
Việc còn lại là sắp xếp các phần tử p
i+1
, p
i+2
, , p
m
theo trật tự tăng dần, hoán vị tìm đợc Q = (q
1
,
q
2
, , q
m
) sẽ là hoán vị cần tìm đợc. Hình vẽ 1.4 Thật vậy, P < Q bởi vì (i-1) thành phần đầu tiên của
chúng trùng nhau và p
1
<q
1
( bởi vì theo cách chọn lựa của mình q
i
= p
j
>p
i
). Trong i thành phần đầu tiên
P là lớn nhất, còn Q nhỏ nhất, bởi vì trong P các thành phần giảm dần , còn Q - tăng dần. Cuối cùng nếu
hoán vị R nằm giữa P và Q, thì i -1 thành phần đầu tiên của nó trùng với các thành phần P và Q, còn
thành phần r
i
= p
1
hay q
i
, bởi vì trong i-1 thành phần đầu tiên đã chiếm chỗ không có những số nằm giữa p
i
và q
i
.
Nếu p
i
= r
i
và P nhỏ hơn hoặc bằng R thì P=R (bởi vì P lớn nhất với các phần tử p
1
, p
2
, ,p
i
cho trớc
) và nếu r
i
=q
i
thì tơng tự ta có R = Q.
CM Soft 70 NCT F2 Q10
CM Soft 70 NCT F2 Q10
VIETBOOK
Trang 10
Trong chơng trình điều này đợc thực hiện nh sau : Ta dùng mảng P chứa các hoán vị hiện tại.
Trớc tiên lấp dần bởi hoán vị đầu tiên của chúng P=(1,2, ,m) và gắn hoán vị đồng nhất (a
1
, a
2
, ,a
m
) của
các thành phần của mảng A cho trớc. Giả sử hoán vị P nhận đợc và hoán vị đáp ứng nó A đợc in. Trong
phần tơng ứng của chơng trình sẽ tìm phần tử p
i
< p
i+1
với chỉ số lớn nhất i. Nếu không có i đó, thì hoán vị
P là cuối cùng. Nếu có i ta sẽ tìm chỉ số lớn nhất j > i mà p
i
< p
j
, rồi đổi chỗ pi và p
j
, sau đó dãy p
i+1
, p
i+2
, ,
p
m
trật tự thay đổi theo chiều ngợc lại: để có trật tự này ngời ta đổi chỗ P
i+1
và P
m
, P
i+2
và P
m-1
, Tới đây
việc nhận đợc hoán vị P tiếp theo đợc kết thúc và hoán vị đáp ứng của nó của mảng A đợc in ra.
Bài toán về hoán vị trở nên khó hơn nếu đòi hỏi hoán vị tiếp theo nhận đợc từ hoán vị trớc đó bằng
cách đổi chỗ hai phần tử cạnh nhau. Bài toán nh trên đợc giải ở chơng trình 80.1.2-2. Chơng trình ngắn
nhng phức tạp. Bạn đọc hãy tự tìm hiểu theo bảng hoán vị, mà chơng trình in ra với m = 4.
1 2 3 4 1 3 4 2
1 4 2 3
2 1 3 4 3 1 4 2
4 1 2 3
2 3 1 4 3 4 1 2
4 2 1 3
2 3 4 1 3 4 2 1
4 2 3 1
3 2 1 4 4 3 2 1
2 4 3 1
3 1 2 4 4 1 3 2 2 1 4
3
1 3 2 4 1 4 3 2
1 2 3 4
80.1.3. Nâng luỹ thừa nhanh
Bình thờng để tính a
k
ngời ta đa vào biến số b, ban đầu gán b:=1 rồi thực hiện nhiều lần các
phép toán : k:=k-1;
B:=b*a .
CM Soft 70 NCT F2 Q10
CM Soft 70 NCT F2 Q10
VIETBOOK
Trang 11
Khi biến cố k trở thành 0 (điều này đòi hỏi k vòng) ta sẽ có b=a
k
ý tởng làm gọn cách tính là nh sau . Ban đầu ta đặt b=1.
Nếu k lẻ , ta thực hiện phép toán :
K:=k-1, b:=b*a
Nếu k chẵn, ta sử dụng đồng nhất thức :
Ak = ( a
2
)
k/2
để biến đổi :
k:=k/2 ; a := a*a
khi k = 0 , biến b sẽ chứa giá trị phải tìm
Để chứng minh ta lí hiệu giá trị cần tìm ak là w và đặt b=1, khi đó ak * b = w (*)
Nếu k lẻ, thì các phép thế : k = k-1 , b = b*a không phá vỡ dấu đẳng thức (*). Nếu k chẵn thì
các phép thế k = k/2, a = a*2 cũng không phá vỡ, nghĩa là b = w. Vậy b là giá trị cần tìm.
80.1.4. Các phép tính số học :
Bài toán này cũng là sự thành lập tất cả các hoán vị. Điểm khác biệt ở đây là có sự lặp lại. Ta viết
biểu thức cho trớc ở dạng :
w = ((((( 1 a
2
2) a
3
3) a
4
4) a
5
5 ) a
6
6.
Trong đó các phần tử của mảng a[2:6] biểu thị dấu các phép tính số học. Ta qui ớc các dấu +, -, *, /
đợc biểu thị qua các giá trị 1, 2, 3, 4.
Vì có thể có nhiều khả năng ( 4
6
>1000 ) nên chúng ta cố gắng tổ chức phép toán một cách tiết kiệm.
Để làm điều này khi tính w chúng ta sẽ ghi các kết quả trung gian vào mảng B[1:6], theo qui định
B
1
=1, B
2
=B
1
a
2
2, ,B
6
=B
6
a
6
6 và w = B
6
Tiếp theo khi lựa chọn các khả năng, ta sẽ cho a6 biến thiên dần theo 1, 2, 3, 4 và v.v
Thuật toán này đợc thể hiện trong chơng trình 80.1.4. Chúng ta giải thích một số ý trong phơng
án BASIC nó ở ngôn ngữ Basic. Các biến m và n biểu thị cho các số 35 và 6. Những dòng đầu tiên của
chơng trình (đến dòng số 60) tốt nhất. Các dòng đó làm công việc khởi động để các toán tử bắt đầu từ dòng
số 60 và các toán tử dùng cho sự lựa chọn phơng án kế tiếp, khởi trị cho phơng án đầu tiên.
Chúng ta xem chơng trình từ dòng số 60. Số hạng đầu tiên a
i
đợc chọn từ dãy a
n
, a
n-1
, ,a
2
không
bằng 4. Nó tăng lên 1 còn tất cả những số hạng trớc nó đợc gán là 1. Bây giờ B
i
đợc tính theo B
i-1
và sau
đó tất cả các thành phần còn lại B
i+1
, B
i+2
, ,B
n
. Phần việc thứ hai không phức tạp lắm bởi các a
j
tơng ứng
bằng 1, nghĩa là chúng biểu thị phép (+). Nên B
n
khác thì giá trị w là không cho trớc và chơng trình
chuyển sang sang dòng 60 để xét khả năng tiếp theo. Nếu B
n
=m thì chơng trình cũng chuyển sang dòng 60
nhng có in ra một khả năng đã tìm đợc.
Trong các chơng trình khác 80.1.4 các kí hiệu có khác nhau : trong Pascal và C vai trò dòng số 60
do nhãn R đảm nhiệm, còn trong Fotran thì do nhãn 2 đảm nhiệm.
80.2.1. Tìm các phần tử bằng nhau .
Để có lời giải chấp nhận đợc cho bài toán này cần phải tránh không chọn các cặp phần tử A[i,j] và
A[p,q] hai lần và không đợc lẫn lộn trong các trờng hợp khi i = p và j = q. Trong chơng trình Fotran các
khó khăn nói trên này đợc khắc phục qua việc chuyển đến mảng một chiều với sự giúp đỡ của toán tử
EQUIALENCE.
80.2.2. Tổng các bình phơng . Chơng trình khá dễ đọc.
CM Soft 70 NCT F2 Q10
CM Soft 70 NCT F2 Q10
VIETBOOK
Trang 12
Bài toán này có thể giải không phải nhờ đến hàm lấy căn bậc hai. Giải dựa trên ý tởng chỉ ra trong
chơng trình 87.3. Bạn đọc tự tìm hiểu chơng trình này, có thể xem lại bài 80.2.2 và dễ dàng khôi phục các
chi tiết.
80.2.3. Các số khác nhau :
Chơng trình 80.2.3. dễ đọc. Nhng có thể đẩy nhanh tốc độ thực hiện nó, khi so sánh các phần tử
thử nghiệm không phải với các phần tử trớc đó mà với các phần tử sau nó, đến khi gặp sự trùng đầu tiên. Số
lần do đó sẽ giảm từ m*n đễn m*k, với m là số lợng các số, còn k là số các số khác nhau trong mảng cho
trớc. Chơng trình 80.2.3-2 thực hiện điều đó.
80.3.1. Tổng cho trớc các chữ số .
Tất nhiên là có thể dùng 3 vòng FOR lồng nhau :
FOR i:=0 to 9 do
FOR j:=0 to 9 do
FOR k:=1 to 9 do
If i+j+k = n then
WRITELN ( i+10*j + 100*k );
Tuy nhiên lời giải này là tồi vì nó chứa 900 vòng lặp trong khi đó chỉ cần 100 là đủ.
Lời giải tốt hơn chứa đựng vòng lặp kép theo i và j còn k tính theo tổng cho n: k=n-i-j.
Thêm vào sự kiểm tra 1<=k <=9, chúng ta thu đợc chơng trình 80.3.1.
Bạn đọc có thể hoàn thiện chơng trình bằng cách kiểm tra điều kiện n<=27 và còn có thể tăng tốc
độ tính trong trờng hợp n<18.
80.3.2. M+1 trong hệ nhị phân
Chúng ta duyệt các số a
0
, a
1
, thay thế 1 bằng 0 đến số 0 đầu tiên ta thay nó bằng 1 và khi đó
ngừng việc thay thể các số. Cần lu ý rằng lời giải có thể bao gồm n+1 số, chữ chứ không phải n nh trong
điều kiện của đầu bài .
80.3.3. MAX của các MIN
Chơng trình đợc lập sao cho tránh đợc sự xem xét riêng lẻ dòng đầu tiên và mỗi phần tử đầu tiên
của dòng. Ngoài ra, việc xử lý dòng đang xét sẽ dừng khi ta đã biết rằng dòng đó không thể chứa phần tử
cần kiếm.
80.3.4. Hoán vị của 0, 1, 2
Bài toán này không đòi hỏi sự hoán vị, chỉ cần đếm xem có bao nhiêu số 0, 1, 2 trong mảng và điền
vào mảng theo yêu cầu của đầu bài.
Olimpic 81
81.1. Hàm số
Bài toán có thể là không giải đợc bởi vì đoán dạng cho f(n) rất khó, còn ở mỗi bớc giảm đối số n
số, hàm số cần xét, dờng nh là tăng lên. Thực tế, bắt đầu từ hàm số f(2n+1) chúng ta nhận đợc hai hàm
số f(2n+1)=f(n) + f(n+1)
Từ hai đối n và n+1, có một số lẻ. ở bớc tiếp theo nó sẽ sinh ra hai hàm số, v.v Tuy nhiên sau khi
thực hiện bớc thứ hai này , chúng ta chú ý rằng các hàm số sẽ vẫn là 2 ( chứ không phải là 3) và luôn luôn
sẽ là 2.
CM Soft 70 NCT F2 Q10
CM Soft 70 NCT F2 Q10
VIETBOOK
Trang 13
Để chứng minh điều này - đồng thời cho bên cạnh hàm số một biến cho trớc f(n) chúng ta xét thêm hàm :
g(n,i,j) = if(n) + jf(n+1) , 3 đối số n, i, j
Ta dễ dàng kiểm tra công thức truy hồi :
g(2n,i,j) = g(n,i+j,j); g(2n+1,i,j) = g(n,i,i+j)
Khi đó giá trị cần tìm f(n) có thể viết dới dạng :
f(n) = g(n,1,0)
Bằng cách sử dụng nhiều lần công thức truy hồi ta có thể làm cho đối số đầu tiên của hàm số g bằng 0 và
nhận đợc :
f(n) = g(n,1,0) = =g(0,i,j) = j
Công việc còn lại chỉ là hình thức qua diễn đạt ngôn ngữ mà lập trình tuỳ chọn.
81.2 Cặp bốn
Bài toán này chứa một bẫy nhỏ bởi vì thay việc tìm số nhỏ nhất với tính chất cần có ta có thể tìm số
đầu tiên trong quá trình lựa chọn các số hạng. Bạn đọc có thể tăng tốc độ chơng trình Basic, Pascal, và C
nếu để ý rằng với số cần tìm có 2 dạng biểu diễn ( của tổng bình phơng) khác nhau ở số hạng lớn nhất.
81.3 Hình xoáy ốc
Chúng ta chia vòng xoáy ốc thành 4 phần : đoạn ngang từ phải sang trái và đoạn thẳng đứng từ trên
xuống, đoạn ngang từ phải sang trái và đoạn thẳng đứng từ dới lên trên. Trong chơng trình mỗi đoạn
đợc xử lý riêng và đợc nối kết với đoạn khác. Chơng trình kết thúc sau khi đã nạp phần tử cuối cùng k=
n*n
81.4. Các số lập từ các chữ số khác nhau
Chơng trình 81.4. khá rõ ràng
81.5. Chơng trình 81.5 đơn giản.
olimpic 82
82.1.Hình chữ nhật
Ta nhận thấy số lợng hình chữ nhật chính là số lợng các góc tây bắc tức là góc trái trên của
chúng. Chỉ cần không nhầm lẫn trong trờng hợp góc ở trên biên . Các chơng trình 82.1 và 82.1-2 khắc
phục khó khăn trên theo hai cách khác nhau. Lu ý bạn đọc nào muốn làm rút gọn chơng trình 82.1, bằng
việc sử dụng biểu thức ( i > 1 and A[i-1,j] = 0). Biểu thức có chứa lỗi cú pháp khi i = 1 nếu chỉ số bắt đầu
từ 1.
82.2. Sắp xếp phân số
Chơng trình không dùng mảng phụ và không đòi hỏi sự kiểm tra tính tối giản của phân số. Để làm
việc này ta xét phân số m/n và đặt ban đầu m=0, n=1. Chúng ta in m/n, sau đó trong số tất cả các phân số
a/b, lớn hơn m/n và b<=p ( với điều kiện p = 7 ). Chúng ta chọn phân nhỏ nhất. Nếu có i/j <1 thì thay thế
phân số m/n bởi phân số i/j và tiếp tục quá trình này v.v
Chúng ta chỉ ra vai trò đặc điểm của chơng trình :
Với các mẫu số cho trớc b=2, ,p, ta có thể xác định tử số theo a theo công thức a= m*b/n +1. Phân số
m/n khi đó sẽ là tối giản vì nó có mẫu số nhỏ nhất trong tất cả các mẫu số nhỏ nhất trong các phân số bằng
nó. Lu ý thêm rằng để so sánh hai phân số a/b và i/j ta không nên dùng phép chia sẽ phát sinh sai số mà
dùng phép nhân:
(a/b)<(m/n) nếu a*j <b*i.
CM Soft 70 NCT F2 Q10
CM Soft 70 NCT F2 Q10
VIETBOOK
Trang 14
82.3. Tổng theo tập con
Đây là bài toán liệt kê tất cả các tập con của một tập hợp. Bề ngoài nó giống sự liệt kê tất cả các khả
năng nhng đơn giản hơn. Cho b là một số tự nhiên và b
i
là chữ số biểu diễn theo hệ đếm cơ số 2.
B = b
1
+ 2b
2
+ + 2
n-1
b
n
( b
1
=0 hay b
1
=1).
Khi b lần lợt nhận giá trị b=1, 2, , 2
n
1 theo các bộ chỉ số i của các phần tử b
i
=1 lần lợt là các tập
con ( không rỗng ) của tập hợp ( 1, 2, ,n). Vì thế chơng trình có một mảng phụ B với các phần tử của nó
đợc tham chiếu tới nh là các chữ số nhị phân biểu diễn cho số b.
82.4 Số 0 ở cuối
Bài toán dễ dàng giải với việc sử dụng 2 vòng lặp. Vòng thứ nhất chuyển các phần tử khác 0 về đầu
bảng, còn vòng thứ hai điền 0 vào các vị trí còn lại.
82.5 Điểm yên ngựa
Nếu M
i
là min của các phần tử A
ij
ở dòng i, còn M
j
là Max của các phần a
ij
ở cột j thì M
i
<=A
ij
<M
j
.
Điều này cho phép ta có một vài nhận xét sau đây :
a/ Min ở bất kỳ dòng nào không lớn hơn Max ở bất kỳ cột khác, nghĩa là luôn có : M
i
<M
j
.
b/ Nếu đối với bất kỳ i và j nào thoả mãn đẳng thức M
i
=M
j
thì Max của Min trùng với Min của Max,
còn của giao của dòng i với cột j sẽ có điểm yên ngựa.
M
i
= A[i,j] = M
j
(*)
c/ Nếu điểm A[i,j] là điểm yên ngựa (*) đợc thoả mãn và suy ra Max của Min bằng Min của Max.
Việc còn lại là thực thi các điểm nói trên trong chơng trình. ở mỗi dòng chúng ta tìm Min Mi,
trong số các Min này chọn ra Max Ma và ghi lại dòng IO cha nó. Việc tìm Min ở dòng này sẽ dừng lại
nếu nó nhỏ hơn giá trị Ma hiện có.
Sau đó tìm dòng có chứa phần tử Max bằng giá trị tìm đợc Ma. Nếu cột nh thế không có thì không
có điểm yên ngựa. Thực tế ở chơng trình chúng ta sử dụng điều là nếu ở cột không có phẩn tử lớn hơn Ma
thì cột đó sẽ là cột phải tìm theo lý do nêu trong mục a/.
Chú ý rằng nếu chơng trình không sử dụng những lý giải trên đây sẽ chạy chậm hơn.
82.6 Từ trong văn bản
Chơng trình này khá đơn giản.
CM Soft 70 NCT F2 Q10
CM Soft 70 NCT F2 Q10
VIETBOOK
Trang 15
Olimpic 83.
83.1. Đảo bit
Để hiểu rõ đầu bài chúng ta hãy viết ( trong bảng ) một vài giá trị của m và B (m) trong hệ nhị
phân. (Xem bảng)
Hệ thống 10 2 2 10
Giá trị của m và
B(m)
512 1000000000 00000000001 1
513 1000000001 10000000001 513
514 1000000010 01000000001 257
515 1000000011 11000000001 769
516 1000000100 00100000001 129
1023 1111111111 11111111111 1023
Chúng ta thấy rằng chữ số hàng cao nhất của m=512 trong hệ nhị phân biểu thị bởi số 1 , và chữ số
hàng đơn vị của số B(m) tơng ứng các giá trị đó sẽ là
1. Các số hạng sau của dãy là 256 và 2. Hệ số hàng cao nhất của số m luôn là 1 bởi vì m>=512. Ta
khử nó và thay thế bằng số m-512 và mang một đơn vị vào trong B(m). Trong chữ số tiếp theo, đơn vị của
số m sẽ là 1 nếu giá trị mới của m >=256. Nếu nó tồn tại chúng ta khử nó và mang vào trong B(m) số 2.
Chúng ta sẽ kiểm tra sự có mặt của số 1 ở hàng tiếp theo Điều này dẫn đễn chơng trình 83.1. Lu ý rằng
vòng lặp sẽ kết thúc khi m=0.
Chơng trình phải dùng đến 512*10 lần lặp. Chơng trình sẽ nhanh hơn khi xây dựng B(m+1) theo
B(m). Nhìn vào cách viết ở hệ nhị phân giá trị B(m) có thể hình dung rằng khi xây dựng B(m+1) cần phải
duyệt B(m) từ trái sang phải và thay 1 bằng 0 ( nghĩa là phải trừ từ B(m) số 512, 256, ) đến số 0 đầu tiên ta
phải thay thế nó bằng 1 và sẽ nhận đợc số B(m+1). Chơng trình tính một nửa số m theo một vòng, số 7
theo 3 vòng Tất cả sẽ ít hơn 512 * 2 vòng. Chơng trình 83.1-2 đợc xây dựng nh vậy.
83.2. Tam giác và điểm
Chúng ta nhận thấy nh sau : Nếu điểm M(x,y) nằm trên đờng thẳng L12 qua M
1
(x
1
,y
1
) và
M
2
(x
2
,y
2
) thì do sự đồng dạng của tam giác ta có :
(y-y
1
)/(x-x
1
) = (y
2
-y
1
)/(x
2
-x
1
)
Bỏ qua điều kiện bằng 0 của các mẫu số chúng ta viết lại chơng trình dới dạng:
F
12
(x,y) = (x-x
1
)(y
2
- y
1
) (x
2
-x
1
)*(y-y
1
) = 0
Rõ ràng đối với điểm M(x,y) không nằm trên đờng thẳng L12 thì F
12
(x,y)<>0, hơn nữa dễ kiểm tra
F
12
(x,y)<0 đối với điểm nằm bên trái đờng thẳng L12 (Nếu xét theo phơng từ M
1
đến M
2
) và F
12
(xy)>0
đối với điểm năm bên phải L12. Điều đó có nghĩa là điểm M nằm trong tam giác (M
1
,M
2
,M
3
) khi và chỉ khi
3 số:
F
12
(x,y), F
23
(x,y), F
31
(x,y)
Nhận đợc đối với các đờng thẳng L
12
= (M
1
M
2
), L
23
=(M
2
M
3
) và L
31
= (M
3
M
1
) có
CM Soft 70 NCT F2 Q10
CM Soft 70 NCT F2 Q10
VIETBOOK
Trang 16
cùng dấu.
Để giải bài toán dễ dàng chúng ta đa vào 2 mảng X[1 3 ] và Y[1 3] để chứa các toạ độ của các
điểm M
1
, M
2
, M
3
và xác định hàm :
Q(i,j) = sin [(x-x[i]*(y[j]-y[i]) (x[j]-x[i]*(y-y[i])]
Gọi hàm này 3 lần chúng ta tính đợc 3 số t
1
, t
2
, t
3
sau đây :
t
1
= Q(1,2), t
2
= Q(2,3), t
3
= Q(3,1)
Nếu t
1
, t
2
, t
3
bằng nhau thì điểm M nằm trong tam giác, nếu không thì nằm ngoài hoặc ở trên cạnh.
Lời giải khác của bài toán này dựa trên sự so sánh diện tích của tam giác. Chúng ta kí hiệu diện tích
tam giác (M
1
, M
2
, M
3
) là S, còn S
1
, S
2
, S
3
là diện tích các tam giác tạo bởi điểm M với hai đỉnh trong số M
1
,
M
2
, M
3
. Nếu S = S
1
+ S
2
+ S
3
thì điểm nằm trong tam giác, nếu không thì nằm ngoài tam giác. Lời giải này
đợc dẫn ra ở chơng trình Pascal.
Diện tích tam giác đợc tính theo công thức Hê-rông. Điểm đợc coi là nằm ngoài tam giác nếu S
1
+ S
2
+ S
3
> 1,000001*S. Thừa số 1,000001 cần để tính sai số của phép tính.
83.3. Mê cung .
Bài toán quen thuộc này dễ dàng biến đổi. Lời giải chia ra làm hai phần : Tìm con đờng để ra và in
con đờng Ngợc lại , từ lối ra đến xuất phát của du khách.
Lời giải đơn giản của phần thứ nhất nh sau : Ta viết ở các ô A[i,j], nơi xuất phát của du khách số 2
và đặt k = 2. Chúng ta xét tất cả các ô A của mê cung. Đối với đó, nếu gặp số 0, thì ta xét bốn ô liền kề ô đó.
Nếu có ít nhất một trong chúng chứa số k ( lúc này bằng 2 ) thì ta viết vào ô ấy số k+1.
Bây giờ tăng k lên k+1 và lại xét toàn thể các ô A. Quá trình này kết thúc khi số đợc viết ở ô giới
hạn ( lối ra đã tìm đợc ) hoặc sau khi đã xét toàn bộ các ô A số đã cho không đợc viết vào một ô mới nào
(không có lối ra). Có bao nhiêu lần duyệt các ô thì có bấy nhiêu ô ở trên đờng đi ngắn nhất.
Dễ dàng làm tốt hơn thuật toán trên. ở mỗi bớc đi sẽ xem xét tất cả các ô A của mê cung nh trớc.
Nếu trong một ô nào đó ta gặp số không, còn ở ô bên cạnh bất kỳ có số k >=2 thì chúng ta viết vào ô A số
k+1. Rõ ràng lời giải này là phần đầu của bài toán, nhng nếu trôi chảy, thì ở đây lời giải tìm ra nhanh hơn.
Chơng trình sẽ hiệu quả hơn, khi bắt đầu từ ô đầu tiên (nơi bắt đầu số 2 đợc ghi), tìm ra ô bên
cạnh đầu tiên là bỏ trống( nghĩa là với số 0 ). Ghi vào đó số 3 và tìm ô trống bên cạnh viết số 4.v.v Quá
trình sẽ kết thúc nếu đạt danh giới ( có lối ra ) hoặc không có ô trống bên cạnh (ô cụt). Nếu ô cụt là xuất
phát (nơi ghi số 2)thì không có lối ra. Nếu ô cụt khác ô xuất phát và ở đó ghi K >2 , thì ta viết vào đó số 1 (
làm nó không đi qua đợc ) và chuyển sang ô bên cạnh ô đó với số k-1. Ô nh vậy là có và duy nhất. Lời
giải trình bày ở chơng trình 83.3. ở đó dễ dàng nhận ra sơ đồ chung của sự lựa chọn các tình huống.
Có thể làm gọn hơn nữa chơng trình để giải bài toán Mê cung, nếu ta dùng kỹ thuật đệ qui. Điều
này đợc thực hiện ở chơng trình 83.3-2. Tuy nhiên viết chơng trình nh thế dễ hơn là đọc nó.
Các thuật toán đã trình bày (ngoài thuật toán đầu tiên) có thể tìm ra con đờng không ngắn nhất. Để
tiết kiệm tìm kiếm con đờng ngắn nhất trong Mê cung có thể dùng thêm hai mảng X và Y để ghi nhận toạ
độ (x,y) của các ô cần xét. Kỹ thuật này đợc gọi là tìm kiếm theo bề rộng.
Đầu tiên ở X, Y ta ghi toạ độ của ô xuất phát của du khách. ở mỗi bớc, từ mảng X, Y ta xét các toạ
độ các ô hiện có ( với số hiệu b ) còn các ô tự do bên cạnh, theo trật tự bất kỳ, đợc viết tiếp vào X, Y ( với
số hiệu e ). Nh thế danh sách sẽ đợc xử lý ở phía đầu và thêm vào ở phía cuối.
Sự tìm kiếm kết thúc khi tìm đợc ô tự do ở biên hoặc đã xét hết các mảng X, Y ( khi không có lối
ra ). Thuật toán này đợc thực hiện ở chơng trình 83.3-3.
Việc tìm và in con đờng ngợc lại ở các chơng trình không đệ quy là nh nhau, còn ở chơng
trình đệ qui là tự động .
CM Soft 70 NCT F2 Q10
CM Soft 70 NCT F2 Q10
VIETBOOK
Trang 17
83.4. Cái ca .
83.5. Rút gọn phân số .
Có thể viết chơng trình cho thuật toán Ơ-clit để tìm ớc số chung lớn nhất của các số m, n và chia
tử và mẫu cho số này. Đó là chơng trình 83.5.
Chúng ta trình bày bản chất của thuật toán Ơ-clit. Cho m
1
> m
2
, ớc chung lớn nhất ( m
1
, m
2
) là ớc
số chung của cặp ( m
2
, ( m
1
- m
2
) ), do đó là ớc số chung của cặp (m
2
, m
3
) với
m
3
= m
1
- (m
1
/m
2
) * m
2
Là số d của phép chia m
1
cho m
2
, nh thế hiển nhiên m
3
< m
2
. Điều ngợc lại cũng đúng: ớc
chung nào của (m2,m3) cũng là ớc chung của ( m
1
,m
2
). Do đó ( m
1
, m
2
) = ( m
2
, m
3
)
Lần lợt thay thế đối số lớn nhất ở hàm USCLN (m,n) bởi số d của số lớn chia cho số nhỏ, chúng
ta có dãy
( m
1
, m
2
) = ( m
2
, m
3
) = = ( m
k
, 0 ) = m
k
trong đó m
1
>= m
2
>= m
3
>= >= m
k
và m
k
sẽ là ớc số chung lớn nhất của các số ban đầu m
1
, m
2
.
Tuy nhiên nếu n không lớn ta có thể trực tiếp chọn i/j = m/n với mẫu số nhỏ nhất j, nghĩa là phân số
đó tối giản. Chỉ cần kiểm tra đẳng thức giữa các phân số không theo quan hệ bằng nhau mà theo đẳng thức
của các tích i*n = j*m. Điều này đợc trình bày trong chơng trình 83.5-2.
Chú ý rằng chơng trình 83.5-2 có thể đòi hỏi n phép tính, trong khi đó 83.5 luôn cần bậc log
2
n
phép tính.
Olimpic 84
84.1. Nghịch thế .
Làm sạch mảng P bởi số 0. Chúng ta lấy số lần lợt i=1, 2, , n và số T
1
. Chúng ta đi theo các phần
tử P
1
, P
2
, đến khi gặp đợc T
i+1
phần tử 0, và viết vào phần tử cuối trong chúng số i.
84.2. Con đờng.
Ta không thể duyệt tất cả các tình huống i
1
, i
2
, , i
n
, tất cả là m
n
Nhng có thể giải bài toán bằng
phơng pháp qui nạp theo k =1, 2, , n-1.
Cố định số k và k+1 đặt
B[k,i
k+1
] = min (A[i
1
,i
2
,1] + + A[i
k
,i
k+1
,k]
ở đây min đợc lấy theo các tuyển chọn i
1
, i
2
, , i
k
.
Khi đó dễ thấy :
B[1, i
2
] = min ( A[i
1
, i
2
, 1]) với mọi i
1
B[2, i
3
] = min ( B[1,i
2
] + A[i
2
,i
3
,2]) với mọi i
2
B[n-1, i
n
] = min ( B[n-2, i
n-1
] + A[i
n-1
, i
n
, i
n-2
] với mọi i
n-1
Và tìm kiếm :
R = min B[n-1,i
n
] với tất cả i
n
Nh thế, để tính số B[k,
ik+1
] sẽ xem xét m khả năng (lựa chọn i
k
). Đối với k cố định và tất cả các B[k,i
k+1
]
số các khả năng là m
2
, còn toàn bộ bài toán đòi hỏi xem xét ít hơn m
2
* n khả năng.
84.3. Số hoàn thiện.
CM Soft 70 NCT F2 Q10
CM Soft 70 NCT F2 Q10
VIETBOOK
Trang 18
Để giải quyết vấn đề có hay không có số tự nhiên i hoàn thiện có thể xem xét tất cả các số j = 1,
2, , i-1 xem các số nào là ớc số của số 1, cộng những ớc số này. Nh thế chúng ta sẽ có chơng trình
84.3.
Có thể đẩy nhanh chơng trình này, không cần xem xét các ớc số đến i-1 mà chỉ cần tới căn . Để
làm điều đó ta tìm k=i/j ( k>=j), còn nếu j là ớc số của i thì ta sẽ tính không đến j mà đến k. Cần chú ý để
không có ớc số nào đợc lấy 2 lần ( khi j=k). Thuật toán này thực hiện ở chơng trình 84.3-2.
84.4. Chu kì của phân số.
Lời giải phụ thuộc nhiều một số điều không nhắc tới trong đầu bài.
Khi chia số tự nhiên M cho số tự nhiên N ta đợc phần nguyên của thơng và số d :
I = M/N , k = M - i * N ;
Để giải bài toán trớc hết ta loại bỏ từ phân số M/N phần nguyên của nó, bằng cách thay thế số chia M bởi
số d :
M = M - M/N * N.
Bây giờ chúng ta có thể tuần tự nhận đợc các chữ số của số thơng và số d của phân số :
I = 10 * M/N ; m = 10 * M - i * N và v.v
Mỗi số d không vợt quá N, do vậy sẽ không có nhiều hơn N số d khác nhau và chúng bắt đầu lặp
lại. Khi số d bắt đầu lặp lại thì các thơng số bắt đầu lặp lại và các chu kì đợc bắt đầu. Để tìm đợc phần
lặp lại, đơn giản hơn hết là dựa vào mảng D[1:N]. Viết vào đó các số d theo trật tự nhận đợc và so sánh
mỗi số d mới với tất cả các số d trớc.
Lời giải trên đáng tin cậy, nhng không hay, nó đòi hỏi k phép so sánh và xử lý k lần theo phép tính
số d và có thể cần dùng đến n
2
/2 phép so sánh đến tất cả các số d. Hơn nữa ở tất cả các máy hiện đại lấy
phần nguyên M và N khoảng 10
16
, nhng phải mất hàng năm vào việc thực hiện 10
16
phép tính. Vì thế nếu
ta quyết định đa vào mảng D có N số ta sẽ khởi tạo nó và đánh dấu sự xuất hiện của số d lần lợt thứ M
trong phần tử D[M]. Khi đó việc kiểm tra số d theo k mới chỉ cần một phép so sánh. Thuật toán trên thực
hiện ở chơng trình 84.4.
Lời giải này còn nhợc điểm. Số N có thể lớn bao nhiêu tuỳ ý, sao cho N phép tính có thể tiến hành,
nhng đa vào bộ nhớ toán tử mảng N không thể đợc. Chúng ta sẽ tìm kiếm chu kỳ mà không cần đa ra
mảng cho số d.
Trớc tiên chúng ta tách ra từ N bộ phận. Sau đó bỏ qua N chữ số của thơng số. Và bây giờ, khi chu
kỳ rõ ràng bắt đầu, chúng ta ghi nhớ một số d duy nhất và sẽ in chữ số của thơng số tạm thời nó cha lặp
lại. Điều đó thực hiện ở chơng trình 84.4-2. Thú vị là nó ngắn hơn chơng trình trớc.
84.5. Trộn các mảng.
Bài toán quan trọng này về nguyên tắc cần m+n thao tác. Chúng ta lấy từ A, B theo các phần tử thứ
nhất, phần tử nhỏ hơn trong đó chuyển đến C và thay thể bởi phần tử tiếp theo nó trong mảng. Một lần nữa
chúng ta chọn phần tử nhỏ hơn trong hai phần tử chuyển sang mảng C. Và cứ nh thế Sau mỗi phép so
sánh, một phần tử đợc thêm vào C - nghĩa là sẽ có ít hơn m+n phép so sánh. Việc cuối cùng là sao chép các
phần tử ở mảng sang C.
84.6. Lịch
Thuận tiện khi lập mảng M[1:11] với số ngày trong tháng của năm không nhuận. Dễ dàng sử dụng
hàm số Mod(m,n) tìm số d của phép chia m cho n hoặc tơng tự nó.
84.7. Hình vuông.
CM Soft 70 NCT F2 Q10
CM Soft 70 NCT F2 Q10
VIETBOOK
Trang 19
Nếu tất cả các số đứng ở các góc của hình vuông khác nhau, thì tổng của chúng 0+1+5+11=17. Chú
ý rằng mệnh đề đảo cũng đúng. Điều này làm đơn giản chơng trình.
Olimpic 85
85.1. Phân tích ra n số hạng.
Để tránh việc lặp lại sự phân tích trong việc sắp xếp lại các số hạng, chúng ta sẽ chỉ xét những phép
phân tích các số n ra số tự nhiên :
n = m
1
+ m
2
+ trong đó m
1
>= m
2
>=
Chúng ta sắp xếp các kết quả phân tích, giả sử :
n = m'
1
+ m'
2
+ m'
3
+ (m')
n = m''
1
+ m''
2
+ m''
3
+ (m'')
là hai phép phân tích. Chúng ta sẽ coi rằng phép phân tích m' sẽ u thế hơn phép phân tích m'', nếu ở cặp
đầu tiên khác nhau có m'
1
<>m''
1
và m'
1
>m''
1
, nghĩa là : m'
j
= m''
j
với mọi j<i và m'
1
>m''
1
( giống nh khi
so sánh hai xâu kí tự ).
Theo nguyên tắc trên phép phân tích số n = 5 ra các số hạng sắp xếp trong trật tự nh trên sẽ nh sau
:
5 = 5
5 = 4 + 1
5 = 3 + 2
5 = 3 + 1 + 1
5 = 2 + 2 + 1
5 = 2 + 1 + 1 + 1
5 = 1 + 1 + 1 + 1 + 1
Để nhận đợc toàn bộ các phép phân tích số n cho trớc, chúng ta bắt đầu với phép phân tích n = n.
Nếu phép phân tích :
n = m
1
+ m
2
+ (*)
đã nhận đợc thì ta in nó và chuyển sang việc xây dựng phép phân tích trực tiếp sau nó. Để làm điều này khi
di chuyển theo mảng từ phải sang trái, chúng ta sẽ xem xét m
i
, m
i-1
m
k
đến số hạng đầu tiên m
k
lớn hơn 1
. Nếu không có số nh vậy thì phép phân tích thu đợc (*) là cuối cùng và công việc kết thúc. Cho rằng số
hạng m
k
> 1 đã tìm thấy. Giảm m
k
đi một đơn vị và bỏ những đơn vị tiếp theo nó, chúng ta làm giảm toàn
tổng đó một giá trị s = 1+i-k. Bây giờ, đối với j = k+1, k+2, Chúng ta lần lợt xác định các giá trị mới của
các số hạng m
j
. Nếu s > m
k
thì chúng ta đặt m
j
= m
k
và giảm s đi giá trị m
k
. Nếu s<=m
k
thì đặt m
j
= s và ở
đây ta kết thúc một phép phân tích số n ra số hạng.
85.2. Các phần tử bằng nhau :
Cần đa ra mảng j[1:m], để đối với mỗi dòng i ghi nhớ trong j[i] số thứ tự của cột mà chúng ta đã đi
đến ở dòng này và đạt ban đầu tất cả j[i]=1. ứng cử viên các phần tử bằng nhau kí hiệu qua KR , còn việc
xem xét các phần tử của mảng A kí hiệu qua IJ. Ban đầu đặt KR = A[i,j] và i=1. Tiếp theo là bớc viết sơ
đồ khối. Hình 1.5
IJ = A[i,j(t)]
Nếu IJ < KR Nếu
CM Soft 70 NCT F2 Q10
CM Soft 70 NCT F2 Q10
VIETBOOK
Trang 20
IJ=KR Nếu IJ>KR
J[i]=j[i+1] j[i] = j[i] + 1
KR = IJ
i = i+1 i = 1
Hình 1.5
Trớc khi nhận đợc IJ = A[i,j[i]] cần viết kiểm tra sự kết thúc. Nếu i>m thì giá trị cần đã tìm đợc .
Nếu j[i] > n thì không có. Thuật toán này thực hiện ở chơng trình 85.2. Trong chơng trình viết bằng Basic
thay thể các phần tử j[i] bằng các phần tử A[i,0]. Nhng thay thể mảng giúp việc j[1:m] có thể đa vào dòng
giúp việc io[1:m]. Ban đầu dòng đầu tiên của mảng đợc đa vào, còn số các phần tử của dòng io giả định
bằng n. Tiếp theo các dòng i=2, 3, , m của mảng A đợc so sánh với dòng io. ở dòng io chỉ còn lại các
phần tử (và đợc chuyển dịch lên đầu) đợc gặp ở dòng i, còn số n
0
các phần tử còn lại ở dòng io nhận giá
trị mới. Nếu n
0
ở bớc nào đó bằng không, thì không có các phần tử bằng nhau, còn nếu không io[1] sẽ là
phần tử cần tìm kiếmThuật toán này đợc thực hiện ở chơng trình 85.2-2. ở đây trong ngôn ngữ Basic hay
Pascal thay thế các phần tử io[j] bằng các phần tử A(0,j) (tơng ứng với A[0,j]).
85.3. Số không tách đợc.
Bài toán này hay hơn việc có thể chỉ ra từ cách nhìn đầu tiên, vì nó đợc giải sau n*n ( thậm chí sau
n*log n ) phép toán. Đây là lời giải có thể có. Đặt s = 1 và xem xét có hay không trong mảng P phần tử
P[j]<= s nào đó. Nếu không có phần tử nh thế, thì S sẽ là lời giải. Nếu tìm đợc phần tử nh vậy thì thêm
vào giá trị của nó tới S nghĩa là S:= S + P[j]. Loại P[j] khỏi mảng và một lần nữa tìm kiếm, tìm thấy hay
không phần tử trong số còn lại không vợt quá giá trị mới của S và cứ nh thế. Có thể chứng minh bằng qui
nạp ( bạn hãy tự làm điều này ) sẽ tìm thấy nhng số không đợc thiết lập đầu tiên. Thực tế lần lợt ở các
bớc i=1, 2, cần phải xem xét phần tử của mảng P bắt đầu từ P[i], còn phần tử tìm thấy P[j] thay thành
P[i].
Để tiết kiệm số các phép toán (trong trờng hợp các số trong mảng không đợc sắp xếp ), có thể sắp xếp lại
làm cho mảng có trật tự, sau đó so sánh với S sẽ chỉ cần thực hiện với một phần tử của mảng P. Thuật toán
trên đợc thực hiện ở các chơng trình 85.3, 85.3-2.
85.4. Hình tứ diện.
Lời giải chia làm hai phần : Chọn mặt N' để trùng với N'
1
. Phần 1 đợc thực hiện theo 4 cách, còn
phần 2 có 3 cách. Sau khi chọn N', chúng ta còn phải tự viết nốt các mặt của N theo một trật tự nào đó
(chẳng hạn ngợc chiều kim đồng hồ ).
Phần thứ hai của lời giải cần viết dới dạng một hàm số ( Xem chơng trình 85.4 ).
85.5. Kiểu.
Có thể sắp xếp mảng ban đầu, sau đó bằng một lần duyệt ta tính tần số các giá trị và để tìm giá trị
gặp nhiều nhất. Không cần dùng thêm mảng để ghi nhận tần số, mà chỉ cần ghi nhớ giá trị hiện có (xem
chơng trình 85.5 ).
CM Soft 70 NCT F2 Q10
CM Soft 70 NCT F2 Q10
VIETBOOK
Trang 21
Nếu vì lý do nào đó ta không muốn sắp xếp mảng, thì nên làm nh sau. Lần lợt các phần tử A[i] ( đầu tiên
là A[i] đợc so sánh với các phần tử sau nó. Trong trờng hợp này, trớc hết, tần xuất xuất hiện giá trị A[i]
đợc tính, thứ hai, những phần tử A[j] bằng A[i] lần lợt đợc thay thế bởi các phần tử A[i+1], A[i+2], sau
đó nếu nh các phần tử của mảng A đã đợc xem xét và tần xuất k của phần tử A[i] xác định, tần số của
phần tử A[i+k] đợc xác định tiếp theo ( còn những phần tử khác A[i] và A[i+k] đợc bỏ qua ).Thuật toán
này đòi hỏi m*n phép tính, nếu ở mảng có m phần tử khác nhau. Nhng nếu các phần tử khác nhau thì nó
đòi hỏi n*n phép tính ( xem chơng trình 85.5-2).
85.6. Hệ đếm:
Cần tính giá trị số cho trớc theo lợc đồ Hóc ne
N=(( (M[9]*i + M[8]i + + M[2]*i +M[1]
Giả thiết rằng n không vợt quá giá trị lớn nhất cho phép đối với số nguyên. Chỉ số của số N ở hệ đếm j
nhận đợc nh các số d của phép chia nguyên N/j.
K = N/j ; M = N k*j ; N = k ;
Những giá trị của số d M chỉ cần in ra chỉ số chứ không cần nhớ.
85.7. Đờng chéo phụ.
Chúng ta xác định 2 số p = max (1, 1-k ) và q = min(n,m-k). Khi đó giá trị tìm đợc sẽ bằng tổng
các phần tử A[k+j,j], theo tất cả các l = p, p+1, q (nó bằng 0 nếu không có giá trị j nh vậy, nghĩa là nếu
p>q ). Lời giải phải duyệt toàn bộ m*n phần tử mảng A đợc xem là không hợp lệ.
Olimpic 86
86.1. Không có 3 điểm lặp lại.
Dãy cần tìm a
1
, a
2
, , a
i
sẽ đợc xây dựng theo sơ đồ thông thờng của việc duyệt các khả năng.
Chúng ta không diễn giải chi tiết mà chỉ chính xác hoá một số điểm.
Số i sẽ là số bớc đi, các giá trị a
i
=0 và a
i
=1 (hai tình huống của bớc đi này ). Việc kiểm tra là mục
trọng tâm của chơng trình. Ta miêu tả nó.
Sau khi chọn hay thay thế những giá trị a
i
sẽ kiểm tra trong dãy nhận đợc a
1
, a
2
, , a
i
(*), không
một đoạn nào có hạng tử lặp lại 3 lần. Nếu điều kiện này (gọi nó cho ngắn NPT(i) không thoả mãn, thì
không cần xây dựng tiếp dãy (*) mà chuyển qua thay đổi thành phần a
i
( nếu a
i
=1, thì cần thay đổi thành
phần trớc đấy a
i
-1 ). Nếu điều kiện NPT(i) thoả mãn thì chúng ta chuyển sang chọn phần tử tiếp theo a
i
+1
1 2 i-3j i=2j k-j i-j k i
Hình 1.6
Nhng sự kiểm tra này đã đợc làm đối với đoạn a
1
, a
i-1
, nghĩa là, để chọn thành phần ai trong
điều kiện NPT(i-1), và sự lặp lại bộ ba trên đoạn (*) chỉ có thể xảy ra trên đoạn kết thúc tại a
i
, những đoạn
này có độ dài j=1, 2, ,i/3 và mỗi đoạn cần so sánh với hai đoạn trớc đó ( hình 1.6 ). Việc kiểm tra điều
kiện NPT(i) đòi hỏi i
2
phép tính ( với độ chính xác đến thừa số hằng số.
Việc kiểm tra từng đoạn ( độ dài j ) sẽ kết thúc khi gặp sự trùng lặp đầu tiên, còn việc kiểm tra tất cả
các đoạn kết thúc khi tìm thấy một đoạn nào đó lặp lại 3 lần.
Nh chơng trình 86.1 đã viết. Để giảm việc chi phí miền nhớ, mảng A có thể dùng giá trị Bool
(chứ không dùng số) và các phần tử của nó sẽ nhận các giá trị true hoặc false.
86.2. Pô - cô.
Sau đây là một lời giải đơn giản. Tính xem có bao nhiêu cặp bằng nhau có trong mảng A cho trớc.
CM Soft 70 NCT F2 Q10
CM Soft 70 NCT F2 Q10
VIETBOOK
Trang 22
Số lợng trong chúng (đã có sẵn ) duy nhất đặc trng cho tổ hợp. Để tính số cặp bằng nhau, chúng ta làm
bằng 0 bộ ghi S. Chúng ta so sánh mọi phần tử A[i] với tất cả các phần tử tiếp theo A[i] đối với j = i+1,
i+2, và thêm vào S số 1 trong trờng hợp A[i] = A[j].
Điều cần thiết để in câu trả lời p nhận đợc theo giá trị của bộ ghi S trong bảng.
P S S P
4+3+2+1 10 1 1+1 2 5
3+2+1 6 2 1 1 6
2+1+1 4 3 0 0 7
2+1 3 4
Ngoài hai trờng hợp đầu tiên , p = 7 - s
86.3. Cái trống.
Lời giải nh sau là đơn giản nhất. Giả sử k là số thứ tự của véc tơ dự chọn vào phần tử thứ nhất., p là
số thứ tự của véc tơ tiếp theo. Ban đầu k = 1, p=2. Nếu ở thời điểm nào đó xuất hiện :
(1) Xk <= Xp , thì p tăng lên 1
(2) Xk > Xp , thì k đợc thay thế p và p tăng lên 1.
Nếu sau đó p<=12 thì cần chuyển đến việc só sánh các véc tơ Xk và Xp. Nếu p>12, thì số k là lời giải đáp.
Thuật toán này thực hiện ở chơng trình 86.3.
Có thể có lời giải khác. Nó có thể ( ở một vài trờng hợp ) nhanh hơn. Ta đa mảng bổ sung L[1:12]
đối với danh sách các ứng cử ( chính xác hơn danh sách các số thứ tự mà từ đó các ứng cử bắt đầu )
đến véc tơ nhỏ nhất. Ban đầu nạp các số từ 1 đến 12. Sau đó chúng ta lu lại từ chúng những số mà ở đó
phần tử đầu tiên nhỏ nhất, rồi từ chúng những phần tử thứ hai nhỏ nhất, và cứ nh thế cho tới khi không còn
một ứng cử nào hoặc sẽ đợc xem xét cả 12 phần tử ứng cử vào véc tơ nhỏ nhất. Chơng trình 86.3-2
phức tạp hơn nhiều cái trớc đó, để dễ đọc ta qui ớc một số kí hiệu.
i+1 là số hiệu của phần tử các vec tơ ( 0<=i <=11 )
1, j, j
n
là số hiệu của các ứng cử viên thứ 1, tiếp theo và sau cùng ( trong danh sách L q là số thứ tự của
ứng cử viên cuối cùng ( ở bảng L ).
86.4. Tính đơn điệu kép.
Đơn giản nhất là chúng ta đặt i = 1, j = n và so sánh ( đầu tiên cái này, sau đó kế tiếp ) phần tử A[i,j]
với số x.
Nếu A[i,j] = x thì lời giải đã tìm đợc.
Nếu A[i,j] < x thì đặt i = i+1.
Nếu A[i,j] > x thì đặt j = j 1.
Trong hai trờng hợp cần phải kiểm tra rằng còn i<=n, j>=1. Nếu điều nh thế xảy ra thì quay lại
việc so sánh, còn nếu không thì in không có.
ở mỗi bớc chúng ta tăng i hoặc giảm j , suy ra sẽ có không nhiều hơn n+m bớc.
Dễ dàng khẳng định độ tin cậy của thuật toán này. Thực tế nếu đã có A[i,j] < x thì sẽ không có số x
ở dòng i của mảng A[i:m,1:j] và có thể bỏ dòng này. Nếu A[i,j]> x theo nguyên nhân tơng tự có thể loại bỏ
cột j.
CM Soft 70 NCT F2 Q10
CM Soft 70 NCT F2 Q10
VIETBOOK
Trang 23
86.5. Làng trung tâm.
Chúng ta phát biểu bài toán này dới dạng sau : ở mỗi dòng i của mảng A chọn số lớn nhất trong các
số A[i,j] ( i khác j ) và cộng chung với A[i,j]. Tìm i sao cho tổng tơng ứng nhỏ nhất. Theo cách phát biểu
nh vậy bài toán cho lời giải chuẩn.
Olimpic 87.
87.1. Ba lô :
Sau khi loại tất cả các vật nặng hơn 30 kg, ta xếp các vật còn lại theo một thứ tự nào đó và xác định
cây phơng án theo cách sau
Lần lợt ở các bớc i=1, 2, , n ta xét vật với chỉ số i, khi đó sẽ có hai phơng án j của bớc i : j
=0, nghĩa là lấy vật, còn j = 1 là không lấy vật đó ( xem 2.1 về việc đa ra các thuật ngữ ). Lu ý rằng sẽ
nhận đợc cây nhị phân có tất cả các nhánh đều có độ dài n ( nhng không nhất thiết phải hiểu điều này ).
Ngoài những mảng cho trớc A[1:n] và B[1:n] ta đợc thêm mảng T[1:n] và một số biến nữa :
I : Chỉ số của vật tiếp theo
S : Khối lợng của các vật trong ba lô
Z : Tổng trị giá các vật trong ba lô
Zm : Trị giá lớn nhất trong các phơng án đợc xét
P[k] = 0 hoặc P[k]=1, nếu vật k<=i đợc lấy hay không lấy vào ba lô. Ban đầu ta cho I, S, Z, Zm = 0.
Khi xét các phơng án cần phải biết dừng việc chọn các phơng án ngay khi thấy rằng đó là phơng
án ( và tất cả các bớc tiếp theo của nó ) không đáng quan tâm !.
Trong suốt quá trình, ta luôn cố bổ sung thêm vật vào ba lô (nếu S + A[i] < 30). Trong trờng hợp đó
ta sẽ đi theo nhánh trái
S = S + A[i]: Z = Z + B[i] : P[i] = 0
Nếu nh không thể thêm đợc vật, thì ta sẽ không lấy vật đó ( tức là ta sẽ chuyển dịch theo nhánh
bên phải, bỏ tất cả các nhánh phơng án đi về phía trái ) và lu ý rằng P[i] = 1. Trong cả hai trờng hợp ta
đều tiếp tục chuyển dịch về phía trớc cho đến khi xét đến vật cuối cùng.
Nếu tất cả các vật đợc xét, thì phơng án coi nh đã nhận đợc, ta so sánh với Z
m
:
If Z
m
< Z then Z
m
= Z
Và bắt đầu chuyển dịch về phía sau.
Khi chuyển dịch về phía sau bỏ toàn bộ nhóm các vật đợc lấy liên tiếp ( đối với chúng P[i]=0), bởi
vì các thay đổi trong một nhóm nh vậy chỉ có thể làm giảm tổng trị giá các vật trong ba lô. Nhân tiện bỏ
khỏi ba lô các vật đợc xét
If p[i] = 0 then S = S - A[i] :Z = Z - B[i].
Tiếp sau đó ta bỏ toàn bộ các nhóm vật không đợc lấy trớc đó ( đối với chúng P[i] = 1), bởi sự
thay đổi ở nhóm đó sẽ dẫn đến nhánh bên trái, mà nhánh đó cần phải đánh giá trị trớc.
Tóm lại ta sẽ chuyển dịch về phía sau cho đến khi đạt đợc chỉ số i P[i]=0 và P[i+1] = 1 . Trong quá
trình chuyển dịch đó bỏ khỏi ba lô các vật đã có trong đó. Sau quá trình đó ta sẽ chuyển dịch về phía trớc.
Nếu nh chỉ số i cần tìm không có, thì coi nh công việc đã kết thúc.
Luôn có thể làm tốt hơn chút nữa chơng lựa chọn. Chẳng hạn có thể đa vào biến Z
s
của tổng giá trị
các vật đa vào ba lô, và của những vật còn cha đợc xét ( ở nhánh đã cho ). Điều đó cho phép bỏ nhánh,
khi thấy
CM Soft 70 NCT F2 Q10
CM Soft 70 NCT F2 Q10
VIETBOOK
Trang 24
Z
s
<= Z
m
.
Bạn đọc tự làm lấy điều này.
87.2. Nửa bội.
Ta sẽ nhận đợc và nhớ ở mảng A[1:n]các nửa bội theo thứ tự tăng dần. Giả sử đã nhận đợc i nửa
bội đầu tiên :
A[1]< <A[i] (*)
Và giả sử đã biết K
2
và K
3
là các chỉ số nhỏ nhất của các số có trong (*), mà
A
2
= 2 * A[K
2
] + 1 và A
3
= 3 * A[K
3
] + 1
Còn cha có trong (*)
Ta xét xem điều gì sẽ xảy ra khi thêm vào (*) thêm một hạng tử nữa. Rõ ràng
A[i+1] = MIN ( A
2
A
3
)
Nếu A[i+1] = A
2
, thì K
2
đợc tăng thêm 1
Còn nếu A[i+1] = A
3
thì K
3
đợc tăng thêm 1
( Nếu A[i+1]=A
2
=A
3
, thì cả hai số K
2
và K
3
đều đợc tăng thêm 1 )
Trớc hết i=1, A[1]=1, K
2
=1, K
3
=1
Các hạng tử tiếp theo là A[2], A[3], sẽ đợc tính theo thuật toán đã nêu
87.3 Tổng các lập phơng.
Ta lấy M=0, I=1, còn J là số đầu tiên làm cho J
3
+1 >=N. Đặt K = I
3
+J
3
và so sánh K với N. Có thể
xảy ra 3 trờng hợp sau :
(1) : Nếu k < N thì lấy i=i+1 ;
(2) : Nếu k > N, thì lấy j=j-1 ;
(3) : Nếu k=N , thì lấy M = M + 1; J = J-1 ; i = i+1
Các cách tính đó sẽ lặp đi lặp lại cho đến khi k=J
Còn có thể lu ý rằng, trong trờng hợp (3) thay cho i=i+1 có thể viết ngay i=i+2,
Bởi lúc đầu i<=j<=N
1/3
+1 và ở mỗi bớc hoặc i tăng lên 1 hoặc j giảm đi 1, nên số lợng bớc
không vợt qua N
1/3
Để chứng minh sự đúng đắn của thuật toán ta kí hiệu
P[i,j] = {(x,y)} là tập hợp tất cả các cặp số tự nhiên x,y mà
I<=x<=y<=j và x
3
+ y
3
= N
Đặt K = i
3
+ j
3
. Nếu K<N, thì đối với mọi cặp (x,y) từ P(i,j) ta đều có
i
3
+ j
3
< x
3
+ y
3
nhng y<=j, suy ra i < x và nghĩa là nếu K < N, thì P(i,j) = P(i+1,j)
Tơng tự
Nếu K > N, thì P(i,j) = P(i,j-1)
Cuối cùng, khi K = N, sau khi bỏ các cặp (i,j) từ P(i,j) , ta sẽ có nếu K=N, thì P(i,j)\(i,j) = P(i+1,j-1)
CM Soft 70 NCT F2 Q10
CM Soft 70 NCT F2 Q10
VIETBOOK
Trang 25
87.3. Lật ngợc :
Bài toán này cần có sự tinh ý nhất định, để giảm xuống còn N
2
phép toán. Cần phải định đợc tâm
của đoạn đang xét ( điều này cho N phơng án ) và về cả hai phía của tâm cần phải so sánh các phần tử đối
xứng nhau ( điều này cần không quá N nhóm phép toán ). Nh vậy sẽ tìm đợc lời giải sau N2 phép toán (
chính xác đến một thừa số hằng ).
Khi trình bày lời giải thay cho tâm cùng đoạn ( mà có thể trùng với một phần tử hoặc nằm giữa các
phần tử ), để cho tiện có thể lấy chỉ số của 2 phần tử LN<PN cạnh tâm . Các chỉ số đó sẽ đợc chuyển
dịch theo cách tự nhiên :
(LN,PN) = (1,2), )1,3), (2,3), (2,4),
Còn các chỉ số L và P của các phần tử cần so sánh ban đầu đợc lấy
L=LN : P = PN
Còn sau đó ở mỗi bớc ta làm L=L-1:P=P+1
Cho đến khi các phần tử cần so sánh A[L] và A[P] trở thành không bằng nhau hoặc một trong các
điểm L hoặc P vợt ra khỏi phạm vi [1,N].
Khi đó đoạn lớn nhất với tâm (LN,PN) sẽ có độ dài M=P - L - 1
Và độ dài đó có thể sẽ đợc so sánh với MX lớn nhất đã đạt đợc
Sự chuyển dịch tâm (LN,PN) sang biên bên phải của mảng A[1:N] có thể ngừng, nếu đã thoả mãn
bất đẳng thức 2*(N - PN +1) <= MX
Và nghĩa là đoạn đang xét đã không thể làm tăng giá trị của đại lợng MX
87.5 Chỉ số thứ tự.
Đơn giản nhất là đa vào thêm mảng I[1:n] đối với các chỉ số thứ tự cần tìm, điền thêm vào đó lúc đầu
bởi các số 1, 2, , N, và sau đó khi sắp thứ tự mảng A đã cho theo một cách nào đó, ta xếp theo đúng thứ
tự đó các phần tử của mảng I. Khi đó A sẽ đợc xếp thứ tự, I sẽ là cái cần tìm. Điều này đợc làm trong
chơng trình 87.5, ở đó đã sử dụng phơng pháp xếp thứ tự đơn giản nhất:
Trong mảng A tìm phần tử nhỏ nhất và phần tử đó đợc đổi chỗ với phần tử đầu tiên. Sau đó cách làm
này đợc áp dụng cho đoạn A[2:N] và cứ thế mãi .
Nếu để làm phức tạp chơng trình, thì có thể không cần mảng I, nhng vẫn không thay đổi các phần tử
của mảng A. Chỉ cần in và ghi nhớ chỉ số của phần tử nhỏ nhất (MI) tiếp theo. Tất nhiên, trớc hết cần tìm
chỉ số của phần tử đầu tiên đó và chỉ số của phần tử nhỏ nhất đầu tiên ( MA). Điều này đợc làm trong
chơng trình 87.5-2.
olimpic 88.
88.1. Lớn nhất ở bên phải:
Để giải bài này cần sử dụng hai đặc điểm sau. Thứ nhất mảng A[1:n] sẽ đợc xét từ cuối lên ; thứ hai
đa thêm mảng bổ trợ B[1:n] từ các phần tử của mảng A mà có thể có lợi cho việc xét sau này mảng A để
thay các phần tử của nó. Chính xác hơn là vào thời điểm xem xét phần tử A[i] tiếp theo trong mảng B sẽ tìm
các phần tử A[j] (j>1) lớn hơn tất cả các phần tử A[i+1:j-1]. Các phần tử trong mảng B đợc phân bố theo
đúng thứ tự của chúng ở trong A nhng sẽ đợc dịch chuyển sang biên bên phải, chiếm một đoạn B[k:n] nào
đó. Các mảng A và B đợc xử lý đồng thời. Trớc hết đặt
k=n ; B[k]=A[n] ; A[n]=0
Khi xét phần tử A[i] tiếp theo, tất cả các phần tử trên đoạn A[i+1:n] đều đã đợc thay và mảng B[k:n] đã
đợc lấp theo cách cần thiết Trong mảng B[k:n] tìm phần tử đầu tiên B[i] > A[i].
CM Soft 70 NCT F2 Q10
CM Soft 70 NCT F2 Q10