ĐỊNH HƢỚNG CHUYÊN MÔN o b ng h ọc A ĐỊNH...

64
1/64 ĐỊNH HƢỚNG CHUYÊN MÔN trong đào tạo bồi dƣỡng học sinh năng khiếu Tin hc A ĐỊNH HƢỚNG Các cuc thi Olympic Tin học được trin khai rng rãi gn hết các nước trên thế giới hướng ti các mục đích: Đẩy mnh phong trào dy và hc Tin hc nhằm đáp ứng các yêu cu ca cuc sống đang được tin hc hóa sâu rng và vi tốc độ cao trong mi lĩnh vực, Phát hin các nhân tni bật để đào tạo và khai thác ngun nhân lực đỉnh cao, có tri thc và có tay nghtheo kp sphát trin ca lý thuyết và yêu cu ca thc tế. Việc đào tạo, bồi dưỡng hc sinh gii Tin hc chịu tác động rt nhiu ca hai yếu t: Sphát trin ca lý thuyết, Sphát trin ca công cTin hc. Có ththấy rõ xu hướng dy và hc Tin học cho đến nay chia thành ba giai đoạn: Giai đoạn I: nhng năm cuối ca thế kXX, Giai đoạn II: Thp kđầu tiên ca thế kXXI, Giai đoạn III: Thp kth2 ca thế kXXI, tc là những năm hiện ti. giai đoạn I, ngành Tin hc mi tách ra và phát trin thành mt ngành khoa học độc lập. Người ta tp trung mi sc lc vào vic xây dng nn móng cho mt ngành khoa hc mi, cgắng tìm cách để gii quyết được các lp bài toán truyn thng xut hin khi tiếp cn bài toán trên quan điểm toán hc. Vic nm vng các kiến thc toán học là điều kin chyếu để gii quyết các bài toán tin hc. Ngoài ra còn phải lưu ý tới cc ràng buc tnhiên vbnhnhvà tc độ tương đối thp ca máy tính lúc by giờ. Đó là sự tiếp tc của tư duy những năm 70 – 80 ca thế k20. Ví d, bài Hình vuông diu k(Bài 3 ngày 2 IOI 1996) vào thời điểm đó là một bài khó. Hình vuông diu k

Transcript of ĐỊNH HƢỚNG CHUYÊN MÔN o b ng h ọc A ĐỊNH...

Page 1: ĐỊNH HƢỚNG CHUYÊN MÔN o b ng h ọc A ĐỊNH HƢỚNGchuyenlequydonlaichau.edu.vn/upload/32237/20190808/P_He_2011.pdf · Việc đào tạo, bồi dưỡng học sinh giỏi

1/64

ĐỊNH HƢỚNG CHUYÊN MÔN

trong đào tạo – bồi dƣỡng học sinh năng khiếu Tin học

A – ĐỊNH HƢỚNG

Các cuộc thi Olympic Tin học được triển khai rộng rãi ở gần hết các nước trên

thế giới hướng tới các mục đích:

Đẩy mạnh phong trào dạy và học Tin học nhằm đáp ứng các yêu cầu của

cuộc sống đang được tin học hóa sâu rộng và với tốc độ cao trong mọi

lĩnh vực,

Phát hiện các nhân tố nổi bật để đào tạo và khai thác nguồn nhân lực đỉnh

cao, có tri thức và có tay nghề theo kịp sự phát triển của lý thuyết và yêu

cầu của thực tế.

Việc đào tạo, bồi dưỡng học sinh giỏi Tin học chịu tác động rất nhiều của hai

yếu tố:

Sự phát triển của lý thuyết,

Sự phát triển của công cụ Tin học.

Có thể thấy rõ xu hướng dạy và học Tin học cho đến nay chia thành ba giai

đoạn:

Giai đoạn I: những năm cuối của thế kỷ XX,

Giai đoạn II: Thập kỷ đầu tiên của thế kỷ XXI,

Giai đoạn III: Thập kỷ thứ 2 của thế kỷ XXI, tức là những năm hiện tại.

Ở giai đoạn I, ngành Tin học mới tách ra và phát triển thành một ngành khoa

học độc lập. Người ta tập trung mọi sức lực vào việc xây dựng nền móng cho

một ngành khoa học mới, cố gắng tìm cách để giải quyết được các lớp bài toán

truyền thống xuất hiện khi tiếp cận bài toán trên quan điểm toán học. Việc

nắm vững các kiến thức toán học là điều kiện chủ yếu để giải quyết các bài toán

tin học. Ngoài ra còn phải lưu ý tới cấc ràng buộc tự nhiên về bộ nhớ nhỏ và tốc

độ tương đối thấp của máy tính lúc bấy giờ. Đó là sự tiếp tục của tư duy những

năm 70 – 80 của thế kỷ 20.

Ví dụ, bài Hình vuông diệu kỳ (Bài 3 ngày 2 IOI 1996) vào thời điểm đó là một

bài khó.

Hình vuông diệu kỳ

Page 2: ĐỊNH HƢỚNG CHUYÊN MÔN o b ng h ọc A ĐỊNH HƢỚNGchuyenlequydonlaichau.edu.vn/upload/32237/20190808/P_He_2011.pdf · Việc đào tạo, bồi dưỡng học sinh giỏi

2/64

Những thành công của khối lập phương kỳ diệu đã là động lực để ông Rubic đề

xuất phương án phẳng của trò chơi nổi tiếng này. Đó là một bảng gồm 8 hình

vuông xếp thành 2 hàng (xem

hình vẽ).

Trong bài này chúng ta xét

phương án khi mỗi hình vuông

được tô một màu khác nhau. Màu

được đánh bằng tám số nguyên

dương đầu tiên (xem hình vẽ).

Cấu hình của bảng được xác định

bằng cách cho màu của các hình

vuông, bắt đầu từ hình ở góc trên

trái và đi theo chiều kim đồng hồ. Ví dụ, ở hình bên cấu hình ban đầu của bảng

được xác định bởi dãy (1, 2, 3, 4, 5, 6, 7, 8).

Có 3 phép biến đổi cơ sở ký hiệu là „A‟, „B‟ và „C‟ tác động lên bảng:

„A‟: Hoán đổi vị trí 2 dòng trên và dưới,

„B‟: Đẩy vòng tròn cột cuối lên cột đầu,

„C‟: Đẩy vòng tròn theo chiều kim đồng hồ 4 hình vuông ở giữa.

Cho một cấu hình cuối của bảng. Nhiệm vụ của bạn là viết chương trình xác

định dãy phép biến đổi cơ sở đưa bảng từ trạng thái ban đầu nêu ở hình bên về

trạng thái cuối đã cho (Bài toán con A). Bạn sẽ nhận thêm 2 điểm thưởng nếu số

phép biến đổi trong lời giải của bạn không quá 300.

Dữ liệu: vào từ file INPUT.TXT gồm một dòng chứa 8 số nguyên mô tả trạng

thái cuối của bảng.

Kết quả: Đưa ra file OUTPUT.OUT, dòng đầu tiên chứa số nguyên L – độ dài

của dãy phép biến đổi. Mỗi dòng trong L dòng sau chứa một ký tự - tên phép

biến đổi cần thực hiện.

Công cụ trợ giúp: Chương trình MTOOL.EXE trong thư mục chứa đề bài được

cung cấp để thử nghiệm thực hiện các phép biến đổi và xác định trạng thái cuối

của bảng. Lời gọi chương trình có dạng “MTOOL input.txt

output.txt”.

Ví dụ:

INPUT.TXT OUTPUT.TXT

1 2 3 4

8 7 6 5

1 2 34

8 7 65

1 7 2 4

8 6 3 5

1 2 3 4

8 7 6 5

Trạng thái ban đầu

Phép

biến

đổi

A

Phép biến đổi C

Phép biến đổi

B

Phép biến đổi

B

Phép biến

đổi A

Phép biến

đổi C

Page 3: ĐỊNH HƢỚNG CHUYÊN MÔN o b ng h ọc A ĐỊNH HƢỚNGchuyenlequydonlaichau.edu.vn/upload/32237/20190808/P_He_2011.pdf · Việc đào tạo, bồi dưỡng học sinh giỏi

3/64

2 6 8 4 5 7 3 1 7

B

C

A

B

C

C

B

Phân tích: Số lượng trạng thái khác nhau của bảng là 8! = 40 320. Việc tổ chức

loang và lưu trữ vết loang từ trạng thái ban đầu tới trạng thái đích trong điều

kiện hiện nay không phải là một chuyện khó. Nhưng vào thời điểm diễn ra kỳ

thi, bộ nhớ có thể được sử dụng chỉ là 64KB + 64KB cấp phát động và máy

thực hiện thuộc loại 386 thì đó là cả một vấn đề lớn.

Chúng ta đã đạt được những kết quả rực rỡ trong thời kỳ này vì đội ngũ giáo

viên tin học phần lớn xuất thân từ giáo viên chuyên ngành toán. Học sinh của

chúng ta được trang bị kiến thức cơ sở về toán khá tốt.

Giai đoạn II từ những năm 2001 đến 2007, sự tiến bộ về công nghệ và sự phổ

cập của các hệ thống phần mềm tiên tiến đã đưa đến những sự chuyển dịch

trong việc đào tạo chuyên gia trong lĩnh vực tin học. Điều này dẫn đến những

thay đổi trong công tác phát hiện, đào tạo và bồi dưỡng học sinh giỏi tin học.

Do đó nội dung thi Tin học Quốc tế cũng có nhiều thay đổi. Các kiến thức giải

thuật được coi là đỉnh cao trước đây bây giờ đã trở thành “bảng cửu chương”

mà ai cũng phải biết và phải thuộc. Những giải thuật phức tạp, ít dùng thì không

nhất thiết phải thuộc, nhưng bất cứ ai và lúc nào cũng có thể tra cứu, tìm kiếm

chúng trên Internet khi cần thiết. Sự thông minh và tính sáng tạo bây giờ phải

thể hiện không phải ở chổ bạn thuộc nhiều hay ít các giải thuật khác nhau, cũng

không phải bạn cài đặt chúng nhanh tới mức nào. Thử thách bây giờ là ở chổ

bạn có thể tìm ra những giải pháp hữu hiệu giải quyết một cách có hiệu quả các

bài toán các vấn đề có mô hình toán học đơn giản nhưng có kích thước lớn hay

không?

Để đạt được mục đích đó người lập trình phải biết tận dụng tối đa khả năng mà

phần cứng và hệ điều hành cung cấp. Các hệ thống lập trình mới như Free

Pascal, Dev C++ (những phiên bản đầu tiên) đã tạo điều kiện để người dùng

khai thác được tối đa khả năng của phần cứng.

Đáng tiếc là tới tận năm 2007 khi thế giới đã đi hết chặng đường quan trọng này

thì chúng ta mới được phép chính thức đặt chân lên mãnh đất đã in đầy dấu

Page 4: ĐỊNH HƢỚNG CHUYÊN MÔN o b ng h ọc A ĐỊNH HƢỚNGchuyenlequydonlaichau.edu.vn/upload/32237/20190808/P_He_2011.pdf · Việc đào tạo, bồi dưỡng học sinh giỏi

4/64

chân của những người tiên phong, đi vào con đường vốn bây giờ đã trở thành kỷ

niệm đẹp của những người đi trước.

Ở giai đoạn III, tức là ở những năm gần đây, trong danh mục yêu cầu đối với

người lập trình có thêm các đòi hỏi mới:

Không những bạn phải đứng vững trên nền tảng của phần cứng và hệ

thống mà còn phải biết khai thác tối đa khả năng của công cụ lập trình.

Cụ thể, bạn phải khai thác được triệt để mặt mạnh của các thư viện của

hệ thống lập trình có trong tay,

Nâng cao tính hoàn thiện của chương trình: chương trình phải cho kết quả

đúng và xử lý có hiệu quả với từng lớp dữ liệu (của bài toán).

Phải biết tạo một chương trình linh hoạt, kết hợp vài loại giải thuật để giải

một bài toán vốn rất đơn giản nếu kích thước bé.

Page 5: ĐỊNH HƢỚNG CHUYÊN MÔN o b ng h ọc A ĐỊNH HƢỚNGchuyenlequydonlaichau.edu.vn/upload/32237/20190808/P_He_2011.pdf · Việc đào tạo, bồi dưỡng học sinh giỏi

5/64

Ví dụ, bài Vườn bách thảo (Thi toàn Liên bang Nga 04/2011).

VƢỜN BÁCH THẢO

Trong vườn bách thảo có một khu đất hình chữ nhật kích thước w×h trồng một

loại cây đặc biệt quý hiếm. Với mỗi cây người ta làm một lối đi tạo thành hình

vuông có cây ở tâm. Kích thước hình

vuông phụ thuộc vào vùng bộ rễ của cây

lan tới. Nếu tạo hệ tọa độ để khu đất này

có 2 đỉnh đối là (0, 0) và (w, h) thì đỉnh

tất cả các hình vuông đều có tọa độ

nguyên. Hai hình vuông bất kỳ không có

phần chung diện tích khác 0, tổng diện

tích các hình vuông có cây đúng bằng

diện tích khu đất, cạnh hình vuông song

song với trục tọa độ.

Thời gian trôi đi và cỏ mọc um tùm che

kín các lối đi. Người ta cần vẽ bản đồ

khôi phục lại các lối đi để lập trình điều

khiển rô bốt chăm sóc cây.

Yêu cầu: Cho w, h, n, xi, yi, trong đó n

là số cây, (xi, yi) – tọa độ cây thứ i (1 ≤ w, h ≤ 1012

, 1 ≤ n ≤ 2×105). Hãy xác

định độ dài cạnh hình vuông bao quanh mỗi cây. Dữ liệu đảm bảo tồn tại lời

giải.

Dữ liệu: Vào từ file văn bản GARDEN.INP:

Dòng đầu tiên chứa 3 số nguyên w, h và n,

Dòng thứ i trong n dòng sau chứa 2 số thực xi và yi.

Kết quả: Đưa ra file văn bản GARDEN.OUT n số nguyên trên n dòng, dòng

thứ i chứa cạnh hình vuông có tâm là cây thứ i.

Ví dụ:

GARDEN.INP GARDEN.OUT 4 6 3

1 1

3 1

2 4

2

2

4

Phân tích: Để đạt được điểm tối đa cần phải biết tổ chức lưu trữ dữ liệu dưới

dạng đồ thị cây, thực hiện các phép xử lý cây, tổ chức tìm kiếm nhị phân trên

trên đó.

x

y

1

1

(w, h)

Page 6: ĐỊNH HƢỚNG CHUYÊN MÔN o b ng h ọc A ĐỊNH HƢỚNGchuyenlequydonlaichau.edu.vn/upload/32237/20190808/P_He_2011.pdf · Việc đào tạo, bồi dưỡng học sinh giỏi

6/64

Các hệ thống lập trình như Free Pascal 2.4.4, Dev C++ 4.9.9 đều cung cấp

những thư viện khổng lồ hỗ trợ người dùng và đều có thể mang lại những hiệu

quả tương đương trong lập trình. Tuy vậy C++ nhận được sự lựa chọn đông đảo

thí sinh dự thi hơn vì các lý do:

Thư viện chuẩn hộ trợ lập trình của C++ dễ tiếp cận hơn vì có nhiều tài

liệu giới thiệu,

Có nhiều phiên bản chương trình dịch miễn phí để những Ban tổ chức

cung cấp cho thí sinh,

Ở nhiều nước lấy C++ làm cơ sở giảng dạy ở trường phổ thông,

Trong tương lai, khi lên đại học người ta sẽ dùng C++ là chủ yếu,

Mặt mạnh của Pascal là khả năng thể hiện có cấu trúc trong quá trình

triển khai giải thuật không còn là trọng tâm trong nội dung giảng dạy,

C++ cho phép xây dựng chương trình tối ưu, thể hiện các tiểu xảo lập

trình.

Tuy vậy, C++ cũng có những mặt yếu của nó so với Pascal. Ta sẽ nói đến

những vấn đề này muộn hơn, khi đề cập tới công cụ lập trình.

B – CÔNG CỤ LẬP TRÌNH

Trang bị kiến thức về ngôn ngữ lập trình chưa bao giờ là một vấn đề lớn trong

tin học. Điều quan trọng là kỹ thuật lập trình và tổ chức dữ liệu. Khi đã biết

tương đối tốt một ngôn ngữ lập trình thì việc chuyển sang lập trình ở một ngôn

ngữ mới khá đơn giản.

Bên cạnh ngôn ngữ truyền thống PASCAL với hệ thống lập trình Free Pascal và

C++ với hệ thống lập trình DEV C++, nhiều nước còn cho phép và khuyến

khích sử dụng một loạt các ngôn ngữ khác như Delphi, Python, Java, C#, v . v .

. .

Đương nhiên, khi chọn một ngôn ngữ nào đó làm công cụ cho mình người lập

trình cần phải:

Biết rõ những điểm mạnh và yếu của ngôn ngữ cũng như của hệ thống hệ

thống lập trình hỗ trợ,

Cần nắm vững các dịch vụ mà hệ thống lập trình cung cấp,

Cần có thói quen suy nghĩ và hành động phù hợp với ngôn ngữ và hệ

thống lập trình,

Cần biết càng sâu càng tốt các thư viện chuẩn hỗ trợ lập trình và biết

khai thác chúng một cách tối ưu.

Page 7: ĐỊNH HƢỚNG CHUYÊN MÔN o b ng h ọc A ĐỊNH HƢỚNGchuyenlequydonlaichau.edu.vn/upload/32237/20190808/P_He_2011.pdf · Việc đào tạo, bồi dưỡng học sinh giỏi

7/64

Nếu có cách tiếp cận hợp lý thì những vấn đề trên có thể giải quyết được một

cách khá đơn giản và hiệu quả.

Ở nước ta, trong bậc PTTH hệ thống lập trình được sử dụng phổ biến là ngôn

ngữ PASCAL với hệ thống lập trình Free Pascal. Ở bậc đại học, ngôn ngữ lập

trình chủ yếu là C/C++ với hệ thống Dev C++.

Trên thế giới nhiều nước sử dụng C++ với các hệ thống lập trình Dev C++ hoặc

tương đươngngay từ bậc phổ thông trung học.

Việc giảng dạy đại trà trong nhà trường không phải là vấn đề thảo luận ở đây.

Nhưng việc trang bị công cụ cho học sinh năng khiếu, phục vụ cho các kỳ thi

Tin học là vấn đề nằm trong tầm xem xét và xử lý của chúng ta.

Các thành phần và cấu trúc tƣơng đƣơng của 2 hệ thống lập trình

Các phép tính số học

Stt PASCAL C/C++ Ví dụ

Pascal C/C++

+ + a + b a + b

- - a - b a - b

* * a * b a * b

/ / a / b a / b

DIV / n div m n / m

MOD % n mod m n % m

Các phép tính quan hệ

Stt PASCAL C/C++ Ví dụ

Pascal C/C++

< < a < b a < b

<= <= a <= b a <= b

= == a = b a == b

>= >= a >= b a >= b

<> != a<>b a!=b

and && Pascal sử dụng các

phép xử lý bit để tạo

biểu thức quan hệ.

or ||

not !

Page 8: ĐỊNH HƢỚNG CHUYÊN MÔN o b ng h ọc A ĐỊNH HƢỚNGchuyenlequydonlaichau.edu.vn/upload/32237/20190808/P_He_2011.pdf · Việc đào tạo, bồi dưỡng học sinh giỏi

8/64

Các phép tính xử lý bit

Stt PASCAL C/C++ Ví dụ

Pascal C/C++

not ~

and |

or &

xor ^

shl <<

shr >>

Khai báo

Lệnh gán

PASCAL

Var i,j,k:integer;

m,n: longint;

a,b:real;

p,d:int64;

x:array[0..20] of longint;

y:array[1..10, 1..5] of longint;

z:array[1..15] of real;

c:char;

s:string;

C++

int i,j,k;

long m,n,x[21], y[10][5];

float a,b,z[15];

long long p,d;

char c;

string s;

PASCAL

a:=y[i,j];

a:=a+b;

a:=a*z[i];

i:=i+1;

k:=i div j;

k:=i mod j;

C++

a=y[i][j];

a+=b; // a=a+b;

a*=z[i];

i++; // ++i;

k=i/j;

k=i%j;

Page 9: ĐỊNH HƢỚNG CHUYÊN MÔN o b ng h ọc A ĐỊNH HƢỚNGchuyenlequydonlaichau.edu.vn/upload/32237/20190808/P_He_2011.pdf · Việc đào tạo, bồi dưỡng học sinh giỏi

9/64

Lệnh IF

Câu lệnh FOR

Lƣu ý: Có thể khai báo biến i cục bộ hóa trong chu trình:

PASCAL

if a<> b then c=c+5;

if a= b then z[i]:=0 else

begin

z[i]:= z[i]+c;

z[n-i]:=z[n-i]-c

end;

C++

if (a!=b) c+=5;

if (a==b)z[i]=0;

else

{z[i]+=c;

Z[n-i]-=c;

}

Đặt điều kiện

trong ngoặc Lưu ý có ;

Lưu ý có ;

Không có then

PASCAL

for i:=1 to n do

begin

. . . .

end;

for j:= n downto 1 do

begin

. . . .

end;

C++

for (i=1;i<=n;i++)

{

. . . .

}

for (i=n;i>0;i--)

{

. . . .

}

C++

for (int i=1;i<=n;i++){ . . . }

for (int i=n;i>0;i--) { . . . }

Page 10: ĐỊNH HƢỚNG CHUYÊN MÔN o b ng h ọc A ĐỊNH HƢỚNGchuyenlequydonlaichau.edu.vn/upload/32237/20190808/P_He_2011.pdf · Việc đào tạo, bồi dưỡng học sinh giỏi

10/64

Tổ chức chu trình có số lần lặp không biết trƣớc

Phần đầu chƣơng trình

Ở PASCAL có thể có hoặc không có phần đầu chương trình:

Ở C++: bắt buộc phải khai báo các thư viện:

PASCAL

repeat

. . . . .

until j=i;

while i<j do

begin

. . . .

end;

C++

do

{

. . . .

} while (i==j);

while (i<j)

{

. . . .

}

PASCAL

Program NIM;

Uses crt, matrix;

Khai báo thư viện

C++

#include <fstream>

#include <iostream>

#include <string>

using namespace std;

Khai báo thư viện,

thừa không sao!

Page 11: ĐỊNH HƢỚNG CHUYÊN MÔN o b ng h ọc A ĐỊNH HƢỚNGchuyenlequydonlaichau.edu.vn/upload/32237/20190808/P_He_2011.pdf · Việc đào tạo, bồi dưỡng học sinh giỏi

11/64

Tổ chức vào ra với file văn bản

Chƣơng trình con và chƣơng trình chính

PASCAL

Const tfi=‟NIM.INP‟;

Tfo=‟NIM.OUT‟;

Var fi,fo:text;

. . . . . . .

Assign(fi,tfi); reset(fi);

Readln(fi,a,b,c);

Close(fi);

. . . . . . .

Assign(fo,tfo);

Rewrite(fo);

Writeln(fo,a,‟ „,b);

Write(fo,c);

Close(fo);

C++

ifstream fi (“NIM.INP”);

ofstream fo (“NIM.OUT”);

. . . . . . . .

fi>>a>>b>>c;

fi.close();

. . . . . . . .

fo<<a<<” “<<b<<endl;

fo<<c;

fo.close();

Trong phần khai báo.

Flies tự động được mở,

PASCAL

Procedure p1(i,j:integer);

Begin . . . End;

Procedure p2;

Begin . . . End;

Function fact(i:integer);integer;

Begin

. . . . . .

fact:=k

End;

. . . . . .

BEGIN

. . . .

END.

C++

void p1(int i,int j)

{ . . . . }

void p2()

{ . . . . }

int fact(int i)

{ . . .

return(k);

}

. . . . . . .

int main()

{ . . . .

}

Page 12: ĐỊNH HƢỚNG CHUYÊN MÔN o b ng h ọc A ĐỊNH HƢỚNGchuyenlequydonlaichau.edu.vn/upload/32237/20190808/P_He_2011.pdf · Việc đào tạo, bồi dưỡng học sinh giỏi

12/64

Ví dụ:

Xử lý xâu

PASCAL Program NIM;

Const tfi='NIM.INP';

tfo='NIM.OUT';

Var a:array[1..1000] of longint;

i,n,g,t,k:longint;

fi,fo:text;

BEGIN

assign(fi,tfi);

reset(fi);

readln(fi,n);

for i := 1 to n do readln(fi,a[i]);

close(fi);

g:=0;

for i:=1 to n do g:=g xor a[i];

k:=0;

for i:=1 to n do

begin

t:=a[i]-(a[i] xor g);

if t>0 then

begin

inc(k);

a[i]:=t

end

else a[i]:=0

end;

assign(fo,tfo); rewrite(fo);

writeln(fo,k);

if k > 0 then

for i:=1 to n do if a[i]>0 then

writeln(fo,i,' ',a[i]);

close(fo)

END.

C++ #include <fstream>

#include <conio.h>

#include <iostream>

#include <stdlib.h>

using namespace std;

int main()

{long n,g,t,k;

ifstream fi ("NIM.INP");

ofstream fo ("NIM.OUT");

fi >> n;

{long a[n+1];

for (long i = 1; i <=n;i++)

fi>>a[i];

k=0;

g=0;

for (long i=1; i <=n;i++) g^=a[i];

if (g>0)

{ for (long i=1;i<=n;i++)

{ t = a[i] – (a[i]^g);

if (t>0)

{k++;a[i]=t;

} else a[i]=0;

}

}

fo<<k<<endl;

if (k>0)

for (long i= 1; i<=n;i++) if

(a[i]>0) fo<<i << " "<<a[i]<<endl;

fi.close(); fo.close();

}

}

Page 13: ĐỊNH HƢỚNG CHUYÊN MÔN o b ng h ọc A ĐỊNH HƢỚNGchuyenlequydonlaichau.edu.vn/upload/32237/20190808/P_He_2011.pdf · Việc đào tạo, bồi dưỡng học sinh giỏi

13/64

Xâu là một trong các loại dữ liệu cơ bản mà các hệ thống lập trình đều phải

cung cấp địch vụ để khai báo, lưu trữ và xử lý.

Cả trong PASCAL và C++ đều có 2 loại xâu:

Trong PASCAL:

o Xâu kiểu string (ngắn và dài),

o Xâu kiểu Pchar trong hệ thống lập trình Free Pascal,

Trong C++:

o Xâu dạng C,

o Xâu dạng C++.

Tồn tại một loạt các dịch vụ cung cấp các phép xử lý xâu loại 2 và chuyển đổi

dạng biểu diễn xâu. Các dịch vụ này được tổ chức trong thư viện Strings của

PASCAL và string của C++.

string s(“ABCD12345abcdABCDE2”);

string ns(“0123456789”);

l=s.size(); // l=s.length(); 19 l

k=s.find(“BC”); // 1 k (bắt đầu từ 0)

m=s.rfind(“BC”); // 14 m

p=s.find_first_of(„C‟); // 2 p

q=s.find_last_of(„C‟); // 15 q

i=s.find_first_of(ns); // 4 i

j=s.find_last_not_of(ns); // 17 j

Page 14: ĐỊNH HƢỚNG CHUYÊN MÔN o b ng h ọc A ĐỊNH HƢỚNGchuyenlequydonlaichau.edu.vn/upload/32237/20190808/P_He_2011.pdf · Việc đào tạo, bồi dưỡng học sinh giỏi

14/64

C++

#include <fstream>

#include <string>

#include <iostream>

using namespace std;

int main()

{ string

s=("ABCD12345abcdABCDE2");

string ns=("0123456789");

int l,k,m,p,q,i,j;

ofstream fo ("xl_xau.out");

l=s.size();

k=s.find("BC");

m=s.rfind("BC");

p=s.find_first_of('C');

q=s.find_last_of('C');

i=s.find_first_of(ns);

j=s.find_last_not_of(ns);

fo<<"L = "<<l<<endl;

fo<<"K = "<<k<<endl;

fo<<"M = "<<m<<endl;

fo<<"P = "<<p<<endl;

fo<<"Q = "<<q<<endl;

fo<<"I = "<<i<<endl;

fo<<"J = "<<j<<endl;

fo.close();

}

XL_XAU.OUT

L = 19

K = 1

M = 14

P = 2

Q = 15

I = 4

J = 17

Page 15: ĐỊNH HƢỚNG CHUYÊN MÔN o b ng h ọc A ĐỊNH HƢỚNGchuyenlequydonlaichau.edu.vn/upload/32237/20190808/P_He_2011.pdf · Việc đào tạo, bồi dưỡng học sinh giỏi

15/64

PASCAL cũng cung cấp những dịch vụ tương tự trong thư viện Strings. Dưới

đây là vài ví dụ nêu trong tài liệu hướng dẫn sử dụng của Free Pascal.

PASCAL

Program Example13 ;

Uses s t r i n g s ;

{ Program to demonstrate the StrScan and StrRScan f u n c t i o n s . }

Const P : PChar = ’ This i s a PCHAR s t r i n g . ’ ;

S : Char = ’ s ’ ;

begin

Writeln ( ’P , s t a r t i n g from f i r s t ’ ’ s ’ ’ : ’ ,StrScan (P, s ) ) ;

Writeln ( ’P , s t a r t i n g from l a s t ’ ’ s ’ ’ : ’ ,StrRScan (P, s ) ) ;

end .

Find_first và Find_last

PASCAL

Program Example14 ;

Uses s t r i n g s ;

{ Program to demonstrate the StrLower and StrUpper f u n c t i o n s . }

Const P1 : PChar = ’THIS IS AN UPPERCASE PCHAR STRING ’ ;

P2 : PChar = ’ t h i s i s a lowercase s t r i n g ’ ;

begin

Writeln ( ’ Uppercase : ’ ,StrUpper (P2 ) ) ;

StrLower ( P1 ) ;

Writeln ( ’ Lowercase : ’ ,P1 ) ;

end .

Chữ hoa và chữ thường

(có công cụ tương đương trong C)

Page 16: ĐỊNH HƢỚNG CHUYÊN MÔN o b ng h ọc A ĐỊNH HƢỚNGchuyenlequydonlaichau.edu.vn/upload/32237/20190808/P_He_2011.pdf · Việc đào tạo, bồi dưỡng học sinh giỏi

16/64

Như vậy, việc dùng PASCAL hay C++ đều có thể giải quyết một cách hiệu quả

các bài toán thi học sinh giỏi. Tuy vậy, trong mọi trường hợp, học sinh cần

được:

Trang bị thêm các kiến thức mới,

Có thói quen khai thác các công cụ trong hệ thống lập trình,

Biết cách sử dụng hợp lý và có hiệu quả các công cụ hiện có.

Đã là một công dạy và học, tại sao ta không làm việc ngay với C++? Điều này

là hoàn toàn khả thi và có lợi vì:

Về mặt pháp lý:

o Bộ Giáo dục cho phép sử dụng C/C++ trong kỳ thi,

o Công cụ: cũng thuộc loại Open Sources (miễn phí),

Về thời gian:

o 02 tiết cho việc giới thiệu cách viết chương trình trên C++,

o 02 tiết cho việc làm quen với môi trường lập trình Dev C++,

o Các kiến thức khác, nếu cần, trang bị dần trong suốt quá trình bồi

dưỡng (theo nguyên tắc “Mưa dầm thấm đất”),

Lợi ích:

o Thư viện chuẩn STL của C++ có nhiều dịch vụ cần thiết với học

sinh (ví dụ như các công cụ sắp xếp theo các giải thuật khác nhau,

các công cụ tìm kiếm, tổ chức stack, heap, xử lý vector, ma trận v.

v. . .),

o Tài liệu: rất phong phú,

PASCAL

Program Example15 ;

Uses s t r i n g s ;

{ Program to demonstrate the StrPos f u n c t i o n . }

Const P : PChar = ’ This i s a PChar s t r i n g . ’ ;

S : Pchar = ’ i s ’ ;

begin

Writeln ( ’ Pos i t ion of ’ ’ i s ’ ’ i n P : ’ , s i z e i n t ( StrPos (P,S)) - s i z e i n t (P ) ) ;

end .

Tìm vị trí xâu con

Page 17: ĐỊNH HƢỚNG CHUYÊN MÔN o b ng h ọc A ĐỊNH HƢỚNGchuyenlequydonlaichau.edu.vn/upload/32237/20190808/P_He_2011.pdf · Việc đào tạo, bồi dưỡng học sinh giỏi

17/64

Về mục tiêu chiến lược lâu dài:

o Các kiến thức về kỹ năng lập trình sẽ được tận dụng triệt để trong

tương lai khi học sinh lên đại học và ra làm việc,

o Đáp ứng yêu cầu về chiến lược đào tạo và nâng cao chất lượng

Giáo dục của nhà nước.

Tất nhiên PASCAL với hệ thống lập trình Free Pascal vẫn được sử dụng song

song như một tùy chọn cho những người yêu thích và vẫn hoàn toàn có thể đạt

kết quả cao trong các kỳ thi.

Các vấn đề cần lƣu ý khi chuyển đổi công cụ

Trong thời gian đầu cần trợ giúp học sinh các vấn đề:

Các loại lỗi cú pháp thường gặp ở giai đoạn đầu,

Cách tạo file dữ liệu,

Kỹ thuật cục bộ hóa biến,

Khai thác giao diện của Dev C++ và các công cụ hiệu chỉnh,

Vấn đề biến đổi kiểu dữ liệu trong biểu thức,

Giới thiệu về sự tồn tại và tác dụng của một số thư viện trong STL.

Tránh trang bị dồn dập kiến thức mới, đặc biệt là về các thư viện. Phong cách

lập trình theo kiểu C++ sẽ tự động được hình thành dần theo thời gian, đúng với

tinh thần “Trăng đến rằm sẽ tròn”.

Các vấn đề này sẽ được xem xét ở các phần tiếp theo.

Page 18: ĐỊNH HƢỚNG CHUYÊN MÔN o b ng h ọc A ĐỊNH HƢỚNGchuyenlequydonlaichau.edu.vn/upload/32237/20190808/P_He_2011.pdf · Việc đào tạo, bồi dưỡng học sinh giỏi

18/64

SẮP XẾP

Hàm sắp xếp nhanh trên C++

void quickSort(int arr[], int left, int right) { int i = left, j = right; int tmp; int pivot = arr[(left + right) / 2]; /* partition */ while (i <= j) { while (arr[i] < pivot) i++; while (arr[j] > pivot) j--; if (i <= j) { tmp = arr[i]; arr[i] = arr[j]; arr[j] = tmp; i++; j--; } }; /* recursion */ if (left < j) quickSort(arr, left, j); if (i < right) quickSort(arr, i, right); }

Trong nhiều trường hợp thường phải sắp xếp đồng thời 2 dãy Chỉ số CS và Giá

trị B, tức là sắp xếp cặp (csi, bi) theo giá trị tăng dần của bi và với những bi

bằng nhau cặp (csi, bi) có csi nhỏ hơn sẽ đứng trước.

SẮP XẾP 2 DÃY

Ta có thể dễ dàng bổ sung mở rộng hàm sắp xếp nêu trên để giải quyết vấn đề

này. Tuy vậy, để tận dụng tối đa các khả năng sắp xếp khác nhau do hệ thống

lập trình cung cấp ta cần tổ chức dữ liệu theo kiểu véc tơ, heap. . . . Chương

trình sắp xếp sẽ có dạng:

Chƣơng trình trên C chuẩn:

#include <stdio.h>

#include <stdlib.h>

#define MAX 100

typedef struct

121 265 147 3 27 Chưa sắp xếp

121 265 147 3 27 Giá trị trục = 7

Giá trị trục

121 265 147 3 27 12 ≥ 7 ≥ 2 đổi chổ

21 265 147 3 127 26 ≥ 7 ≥ 7 đổi chổ

21 75 147 3 1226 7 ≥ 7 ≥ 3 đổi chổ

21 75 143 7 1226 i > j - kết thúc xử lý nhóm

i

i

i

i

i

j

j

j

j

j

21 75 143 7 1226

Xử lý đệ quy các nhóm

21 53 77 12 2614

Page 19: ĐỊNH HƢỚNG CHUYÊN MÔN o b ng h ọc A ĐỊNH HƢỚNGchuyenlequydonlaichau.edu.vn/upload/32237/20190808/P_He_2011.pdf · Việc đào tạo, bồi dưỡng học sinh giỏi

19/64

{

int val, idx; //val: b[i], idx: cs[i]

}Element;

typedef Element Arr[MAX];

int cmpf(const void *a, const void *b);

int main()

{

Arr a = {{5, 4}, {3, 2}, {5, 3}, {5, 1}, {2, 5}};

int n = 5;

qsort(a, n, sizeof(Element), cmpf);

for (int i=0; i<n; i++)

printf("%d %d\n", a[i].val, a[i].idx);

getchar();

}

int cmpf(const void *a, const void *b)

{

return ((((Element *)a)->val - ((Element *)b)->val>0)||

(((Element *)a)->val == ((Element *)b)->val)&&(((Element

*)a)->idx > ((Element *)b)->idx));

}

Chƣơng trình trên C++:

#include <stdio.h>

#include <stdlib.h>

#define MAX 100

typedef class CElement

{

int val, idx; //val: b[i], idx: cs[i]

public:

CElement(int v=1, int i=1)

{

val = v; idx = i;

}

int GetValue()

{

return val;

}

};

int cmpf(const void *a, const void *b);

Page 20: ĐỊNH HƢỚNG CHUYÊN MÔN o b ng h ọc A ĐỊNH HƢỚNGchuyenlequydonlaichau.edu.vn/upload/32237/20190808/P_He_2011.pdf · Việc đào tạo, bồi dưỡng học sinh giỏi

20/64

typedef class CArr

{

int n;

CElement data[MAX];

public:

CArr()

{

}

void Sort()

{

qsort(data, n, sizeof(CElement), cmpf);

}

};

int main()

{

CArr a;

//Nhap du lieu cho a

//....

a.Sort();

//...

//Xuat ket qua cua a

system("PAUSE");

return 0;

}

int cmpf(const void *a, const void *b)

{

return (((CElement *)a)->GetValue() - ((CElement *)b)-

>GetValue());

}

Ghi chú: Nội dung của phần sắp xếp và sắp xếp 2 dãy được biên soạn theo tài liệu của thầy

Nguyễn Thanh Sơn, trường Phổ thông Năng khiếu , Đại học Quốc gia Thành phố Hồ Chí

Minh.

Page 21: ĐỊNH HƢỚNG CHUYÊN MÔN o b ng h ọc A ĐỊNH HƢỚNGchuyenlequydonlaichau.edu.vn/upload/32237/20190808/P_He_2011.pdf · Việc đào tạo, bồi dưỡng học sinh giỏi

21/64

BÀI TẬP VÀ CHƢƠNG TRÌNH

Để hỗ trợ cho việc triển khai giảng dạy trên C++ các bài tập dưới đây sẽ được giới thiệu kèm

theo với lời giải trên ngôn ngữ C/C++ và Pascal (dựa trên cơ sở hệ thống lập trình Free

Pascal). Khi đã có đủ tự tin trong việc lập trình ta sẽ thấy lời giải đưa ra dưới dạng chương

trình hoàn thiện chỉ có tác dụng chủ yếu để tạo tests.

Việc trình bày giải thuật dưới dạng sơ đồ khối cũng không giúp nhiều cho việc nắm bắt giải

thuật mà chỉ hỗ trợ cho việc viết chương trình (coding) được dễ dàng. Ngoài ra, sơ đồ khối

còn hạn chế tính sáng tạo trong việc triển khai giải thuật.

Với mỗi bài toán, quan trọng và cần thiết hơn cả là gợi ý về giải thuật, bao gồm:

Hướng triển khai giải thuật,

Cần có những dữ liệu gì, tổ chức như thế nào, giá trị đầu, cách biến đổi, dẫn xuất,

Những điểm đặc biệt cần lưu ý,

Đánh giá độ phức tạp,

Với một vài khâu xử lý quan trọng: có thể dẫn xuất câu lệnh hoặc đoạn chương trình.

Việc dẫn xuất đầy đủ chương trình cũng rất cần thiết, nhưng chỉ ở giai đoạn đầu của quá trình

đào tạo, bồi dưỡng học sinh.

Việc tổ chức gợi ý giải thuật còn mất nhiều thời gian và công sức hơn cả việc trực tiếp viết

chương trình giải!

Tuyệt đối tránh cung cấp cho học sinh chương trình hoàn thiện ngay từ đầu, khi học sinh

chưa hiểu giải thuật, chưa bắt tay tự mình lập trình.

Lời giải cho các bài tập ở phần đầu được đưa ra ở dạng song ngữ. Ở nửa cuối của phần bài

tập, khi đã có đủ kinh nghiệm với C++, các lời giải chỉ đưa ra ở dạng chương trình trên C++

hoặc C/C++.

Page 22: ĐỊNH HƢỚNG CHUYÊN MÔN o b ng h ọc A ĐỊNH HƢỚNGchuyenlequydonlaichau.edu.vn/upload/32237/20190808/P_He_2011.pdf · Việc đào tạo, bồi dưỡng học sinh giỏi

22/64

TẬP CON Tên chương trình: SUBSETS.???

Cho 2 tập số nguyên X={x1, x2, . . ., xm} và Y={y1, y2, . . ., yn}, trong đó:

x1 < x2 < . . . < xm,

y1 < y2 < . . . < yn.

Nói X có thứ tự từ điển nhỏ hơn Y nếu thỏa mãn một trong hai điều kiện:

i sao cho x1 = y1, x2 = y2 , . . ., xi-1 = yi-1, xi < yi,

m < n và x1 = y1, x2 = y2 , . . ., xm = ym.

Xét tập số nguyên {1, 2, . . ., n}. Từ tập này người ta có thể trích ra các tập con, trong mỗi tập

con các phần tử được liệt kê theo thứ tự tăng dần của giá trị và sắp xếp các tập con nhận được

theo thứ tự tự điển tăng dần. Các tập con được đánh số bắt đầu từ 1.

Ví dụ, với n = 3 ta có các tập con:

1: { 1 }

2: { 1, 2}

3: { 1, 2, 3}

4: { 1, 3 }

5: { 2 }

6: { 2, 3}

7: { 3 }

Yêu cầu: Cho hai số nguyên n và k (1 < n ≤ 60, 1 ≤ k ≤ 260

-1). Hãy xác định tập con thứ k.

Dữ liệu: Vào từ file văn bản SUBSETS.INP gồm nhiều tets, mỗi test cho trên một dòng chứa

2 số nguyên n và k.

Kết quả: Đưa ra file văn bản SUBSETS.OUT, kết quả mỗi test đưa ra trên một dòng chứa các

số nguyên xác định tập tìm được.

Ví dụ:

SUBSETS.INP SUBSETS.OUT 3 2

4 9 1 2

2

Page 23: ĐỊNH HƢỚNG CHUYÊN MÔN o b ng h ọc A ĐỊNH HƢỚNGchuyenlequydonlaichau.edu.vn/upload/32237/20190808/P_He_2011.pdf · Việc đào tạo, bồi dưỡng học sinh giỏi

23/64

1

1 2

1 2 3

1 3

2

2 3

3

1 0

2 1

3 2

4 3

5 4

6 5

7 6

k k-1

k--

i =n-1 ¸ 0

Bit thứ i của

k t

t = 0

di=1di=0

k--

k = 0

i =n-1 ¸ 0

di = 1

Đưa ra i

Exit

T

T

T

F F

F

C++ #include <fstream>

#include <string>

int n,d[61];

long long k,t,t1=1;;

using namespace std;

ifstream fi ("SUBSETS.INP");

ofstream fo ("SUBSETS.OUT");

void xly()

{ k--;

for (int i=n-1; i>=0;i--)

{ t=(t1<<i)&k;

if ( t==0)

{d[n-i]=1; if (k==0) break;k--;}

else d[n-i]=0;

}

for (int i=1;i<=n;i++) if (d[i]==1) fo<<i<<" ";

fo<<endl;

}

int main()

{ while (! fi.eof())

{ fi>>n>>k;

//if (n==0) break;

xly();

}

fi.close();

fo.close();

}

Page 24: ĐỊNH HƢỚNG CHUYÊN MÔN o b ng h ọc A ĐỊNH HƢỚNGchuyenlequydonlaichau.edu.vn/upload/32237/20190808/P_He_2011.pdf · Việc đào tạo, bồi dưỡng học sinh giỏi

24/64

PASCAL Program SUBSETS;

Const tfi='SUBSETS.INP';

tfo='SUBSETS.OUT';

t1:int64=1;

Var n:integer;

k,t:int64;

d:array[1..60] of byte;

fi,fo:text;

Procedure xly;

var i:integer;

Begin

dec(k);

for i:= n-1 downto 0 do

begin

t:=(t1 shl i) and k;

if t=0 then

begin d[n-i]:=1;

if k = 0 then break; dec(k)

end

else begin d[n-i]:=0; end

end;

for i:=1 to n do if d[i]=1 then write(fo,i,' ');

writeln(fo)

End;

BEGIN

assign(fi,tfi); reset(fi);

assign(fo,tfo); rewrite(fo);

while not eof(fi) do

begin

readln(fi, n, k);

xly

end;

close(fi); close(fo)

END.

Page 25: ĐỊNH HƢỚNG CHUYÊN MÔN o b ng h ọc A ĐỊNH HƢỚNGchuyenlequydonlaichau.edu.vn/upload/32237/20190808/P_He_2011.pdf · Việc đào tạo, bồi dưỡng học sinh giỏi

25/64

INTERNET Tên chương trình: INTERNET.???

Giá truy cập internet phụ thuộc vào từng thời điểm trong tuần. Các ngày trong tuần được

đánh số từ 1 đến 7 bắt đầu từ thứ 2. Bảng tính giá gồm n bản ghi (1 ≤ n ≤ 100), sắp xếp theo

thứ tự tăng dần của thời gian, mỗi bản ghi có dạng:

d cc:mm v

trong đó d là ngày trong tuần, cc – 2 số chỉ giờ (chế độ 24 giờ), mm – 2 số chỉ phút, v – giá

mỗi phút truy nhập, là số nguyên (1 ≤ v ≤ 104). Giá truy nhập được giữ nguyên cho đến khi

gặp thời điểm mới ở bản ghi tiếp theo trong bảng. Sau bản ghi thứ n là bảng ghi số 1.

Yêu cầu: Cho bảng tính giá và danh sách xác định m phiên truy nhập mạng (1 ≤ m ≤ 105).

Mỗi phần tử của danh sách có dạng d cc:mm t, trong đó d, cc, mm có ý nghĩa như trong

bảng giá, t – thời gian truy nhập tính theo phút, là số nguyên (1 ≤ t ≤ 109). Các phiên truy

nhập có thể thuộc những tuần khác nhau. Hãy tính chi phí “lướt” mạng.

Dữ liệu: Vào từ file văn bản INTERNET.INP:

Dòng đầu tiên chứa 2 số nguyên n và m,

Mỗi dòng trong n dòng tiếp theo chứa một bảng ghi của bảng giá,

Ở m dòng cuối cùng mỗi dòng chứa một bản ghi về một phiên truy nhập.

Kết quả: Đưa ra file văn bản INTERNET.OUT một số nguyên – chi phí phải trả.

Ví dụ:

INTERNET.INP INTERNET.OUT 2 3

1 09:00 500

5 22:00 200

2 22:42 16

5 21:06 57

2 22:50 1

36100

Page 26: ĐỊNH HƢỚNG CHUYÊN MÔN o b ng h ọc A ĐỊNH HƢỚNGchuyenlequydonlaichau.edu.vn/upload/32237/20190808/P_He_2011.pdf · Việc đào tạo, bồi dưỡng học sinh giỏi

26/64

C++ #include <fstream>

#include <string>

using namespace std;

long n,m,d,v,t,a[10081];

long long r;

string s;

ifstream fi ("INTERNET.INP");

ofstream fo ("INTERNET.OUT");

void nhap()

{ long i,j;

s.reserve(6);

fi>>d>>s>>v;

i=(s[0]-48)*10+s[1]-48;

j=(s[3]-48)*10+s[4]-48;

t= --d*1440+i*60+j+1;

}

void xd_a()

{

memset(a,0,sizeof(a));

for (int i=1;i<=n; i++)

{ nhap();

a[t]=v;

}

for (int i=1;i<=10080;++i)

{if (a[i]!=0) v=a[i];

a[i]=a[i-1]+v;

}

}

void xd_cf()

{long p,q;

p=v/10080; q=v%10080;

r+=a[10080]*p;

if (t+q>10081){r+= (a[10080]-a[t-1]);q-= (10081-t);t=1;}

r+=(a[t+q-1]-a[t-1]);

}

int main()

{fi>>n>>m;

r=0;

xd_a();

for (int i=1; i <=m; i++)

{nhap();

xd_cf();

}

fo<<r;

fi.close(); fo.close();

}

Page 27: ĐỊNH HƢỚNG CHUYÊN MÔN o b ng h ọc A ĐỊNH HƢỚNGchuyenlequydonlaichau.edu.vn/upload/32237/20190808/P_He_2011.pdf · Việc đào tạo, bồi dưỡng học sinh giỏi

27/64

PASCAL Program Internet;

Const tfi = 'INTERNET.INP';

tfo = 'INTERNET.OUT';

Var n,m,d,v,i:integer;

t:longint;

r:int64;

a:array[-1..10079] of longint;

fi,fo:text;

Procedure nhapdl;

var i,j:longint;

s:string[6];

Begin

readln(fi,d,s,v);

dec(d);

i:=(ord(s[2])-48)*10+ord(s[3])-48;

j:=(ord(s[5])-48)*10+ord(s[6])-48;

t:=d*1440+i*60+j

End;

Procedure xd_a;

var i:longint;

Begin

fillchar(a,sizeof(a),0);

for i:=1 to n do

begin

nhapdl;

a[t]:=v;

end;

for i:=0 to 10079 do

begin

if a[i]<>0 then v:=a[i];

a[i]:=a[i-1]+v

end

End;

Procedure xd_cf;

var p,q:longint;

Begin

p:=v div 10080; q:= v mod 10080;

r:=r+a[10079]*p;

if q+t>10080 then

begin r:=r+a[10079]-a[t-1];q:=q-10080+t;t:=0 end;

r:=r+a[q+t-1]-a[t-1]

End;

BEGIN

assign(fi,tfi); reset(fi);

readln(fi,n,m);

xd_a; r:=0;

for i:= 1 to m do

begin

nhapdl;

xd_cf

end;

assign(fo,tfo); rewrite(fo);

write(fo,r);

close(fi); close(fo)

END.

Page 28: ĐỊNH HƢỚNG CHUYÊN MÔN o b ng h ọc A ĐỊNH HƢỚNGchuyenlequydonlaichau.edu.vn/upload/32237/20190808/P_He_2011.pdf · Việc đào tạo, bồi dưỡng học sinh giỏi

28/64

BÁNH XE MAY MẮN Tên chương trình: WHEEL.???

Hồi còn bé Steve được tặng một đồ chơi gọi là bánh xe may mắn. Đó là một cái đĩa có thể quay theo

chiều kim đồng hồ. Vành của đĩa được chia thành n phần bằng nhau, trên mỗi phần có thể ghi một

chữ cái latinh in hoa. Bên ngoài có một kim chỉ đến chữ cái

khi bánh xe dừng. Thiết kế đồ chơi đảm bảo để kim không

bao giờ chỉ đúng vào vạch phân chia. Cứ mỗi lần kim chạm

vào vạch phân chia lại có một tiếng chuông rất êm tai và bộ

đếm số tiếng chuông ở tâm bánh xe lại tăng thêm 1. Để bắt

đầu quay bánh xe người ta phải lắc nhẹ nó rồi mới quay được

và khi lắc bộ đếm trở về 0.

Steve rất thích thú và chơi rất nhiều lần. Steve không bao giờ

ghi các chữ cái trùng nhau trên vành bánh xe.

Thông thường, với một bộ các chữ cái ghi trên vành bánh xe

Steve chơi k lần liên tiếp, sau mỗi lấn quay Steve ghi lại số

hiển thị ở tâm và chữ cái mà mũi tên chỉ tới.

Điều đó diễn ra đã lâu lắm rồi. Cây cối trong công viên thành

phố đã nhiều lần thay lá. Chiếc đồ chơi xinh xắn đã thất lạc đâu đó. Một lần tình cờ Steve tìm thấy

mảnh giấy cũ ghi lại kết quả chơi. Những kỷ niệm đẹp của thời thơ ấu êm dịu, vô tư lự chợt trào lên

như những đợt sóng lừng và Steve không cưỡng nỗi ý nghĩ phải khôi phục lại dòng chữ đã viết trên

bánh xe. Tuy vậy, cũng không loại trừ khả năng do vội vàng, kết quả đã bị ghi sai (ai mà ngờ được

mẫu giấy này lại có giá trị như vậy trong tương lai!) do đó không xác định được những gì đã ghi trên

bánh xe. Ngoài ra, kết quả lần chơi này cũng có thể khá nghèo nàn, không đủ thông tin để xác định

hết các chữ cái đã ghi trên bánh xe.

Yêu cầu: Cho n, k và các giá trị mi, ci, trong đó mi là số ghi được ở lượt quay thứ i, ci – ký tự kim

chỉ ở lượt quay này (2 ≤ n ≤ 25, 1 ≤ k ≤ 100, i = 1 ÷ k). Hãy xác định dòng chữ ghi trên vành bánh

xe kể từ ký tự lần cuối cùng được kim chỉ tới. Nếu thông tin mâu thuẫn thì đưa raxâu chỉ chứa một ký

tự “!”. Nếu một số ký tự không đủ thông tin để xác định thì vào vị trí đó trong xâu đưa ra ký tự “?”.

Dữ liệu: Vào từ file văn bản WHEEL.INP:

Dòng đầu tiên chứa 2 số nguyên n và k,

Dòng thứ i trong k dòng sau chứa 2 giá trị mi và ci.

Kết quả: Đưa ra file văn bản WHEEL.OUT xâu xác định được.

Ví dụ:

WHEEL.INP WHEEL.OUT 8 8

4 V

3 I

7 T

7 A

6 R

5 N

1 O

9 H

HONITAVR

O

H

N

IT

AV

R

9

C++

Page 29: ĐỊNH HƢỚNG CHUYÊN MÔN o b ng h ọc A ĐỊNH HƢỚNGchuyenlequydonlaichau.edu.vn/upload/32237/20190808/P_He_2011.pdf · Việc đào tạo, bồi dưỡng học sinh giỏi

29/64

C++ #include <fstream>

#include <iostream>

#include <string>

using namespace std;

string s,s2;

char c;

long n,k,m,fl,v;

ifstream fi ("WHEEL.INP"); ofstream fo ("WHEEL.OUT");

void chbi()

{

fi>>n>>k;

s=""; fl=0;v=n-1;

for (int i = 0; i<n; i++) s+='?';

}

void xldong()

{ fi>>m>>s2;

c=s2[0];

m%=n;

v-=m;

if (v<0) v+=n;

if (s[v]=='?') s[v]=s2[0];

else

if (s[v]!= c) {fl=1; return;}

}

void gnkq()

{ int i;

if (fl==1) s='!';

else

{i=s.find(c); s+=s;

s=s.substr(i,n);

}

fo <<s;

}

int main()

{

chbi();

for (int i=0; i<k; i++) xldong();

gnkq();

fi.close(); fo.close();

}

Page 30: ĐỊNH HƢỚNG CHUYÊN MÔN o b ng h ọc A ĐỊNH HƢỚNGchuyenlequydonlaichau.edu.vn/upload/32237/20190808/P_He_2011.pdf · Việc đào tạo, bồi dưỡng học sinh giỏi

30/64

PASCAL Program WHEEL;

Const tfi = 'WHEEL.INP';

tfo = 'WHEEL.OUT';

Var n,k,m,i,err,v:integer;

c0,c:char;

s:string[50];

fi,fo:text;

BEGIN

assign(fi,tfi); reset(fi);

readln(fi,n,k);

s:=''; err:=0; v:=n;

for i:= 1 to n do s:=s+'?';

for i:=1 to k do

begin

readln(fi,m,c0,c);

v:=v-m; if v<=0 then v:=v+n;

if ((s[v]<>'?') and (s[v]<>c)) then

begin err:=1; s:='!'; break end;

s[v]:=c

end;

assign(fo,tfo); rewrite(fo);

if err=0 then

begin s:=s+s; s:=copy(s,v,n) end;

write(fo,s);

close(fi); close(fo)

END.

Page 31: ĐỊNH HƢỚNG CHUYÊN MÔN o b ng h ọc A ĐỊNH HƢỚNGchuyenlequydonlaichau.edu.vn/upload/32237/20190808/P_He_2011.pdf · Việc đào tạo, bồi dưỡng học sinh giỏi

31/64

GHI TA Tên chương trình: GUITAR.???

Trong cuộc thi sáng tạo rô bốt Steve đã trình diễn rô bốt chơi ghi ta của mình, một rô bốt,

theo lời mô tả của tác giả “có đến hàng tỷ ngón tay”!

Đàn ghi ta có 6 dây đánh số từ 1 đến 6 và có p phím đánh số từ

1 đến p. Khi chơi nhạc người ta gẩy dây và bấm phím để có các

giai điệu khác nhau. Với mỗi dây, nếu có nhiều phím cùng

được bấm thì âm điệu sẽ được quyết định bởi phím có số cao

nhất. Ví dụ, âm điệu khi gẩy dây số 3 và bấm đồng thời các

phím 5 và 7 sẽ giống như khi ta gẩy dây này và chỉ bấm phím

số 7.

Điều khó khăn nhất khi biểu diễn một bài nhạc là điều khiển

cường độ tức phải gẩy dây nào và bấm phím nào, còn điều

khiển trường độ (thời gian phát một nốt) không phải là quá khó

về phương diện kỹ thuật. Chương trình điều khiển cường độ

của Steve được tối ưu hóa theo hướng giảm số lần chuyển tay

bấm phím xuống còn ít nhất.

Xét bản nhạc có n nốt, nốt thứ i được cho bởi cặp giá trị

nguyên (si, fi), trong đó si – dây cần gẩy và fi – phím cần

bấm (1 ≤ si ≤ 6, 1 ≤ fi ≤ p, i = 1 ÷ n). Bản nhạc cần chơi

theo trình tự thực hiện lần lượt từ nốt 1 đến nốt n. Ví dụ, với n

= 5, p = 15 và bản nhạc là (2, 8), (2, 10), (2, 12), (2, 10) và

(2,5), thao tác bấm phím của rô bốt là bấm phím 8, bấm phím

10, bấm phím 12, nhả phím 12, nhả phím 10, nhả phím 8 và

bấm phím 5, tất cả là 7 thao tác, thực hiện trên dây số 2.

Yêu cầu: Cho n, p và các si, fi (1 ≤ n ≤ 5×105, 2 ≤ p ≤ 3×10

5, i = 1 ÷ n). Hãy xác định số

thao tác bấm phím ít nhất cần thực hiện.

Dữ liệu: Vào từ file văn bản GUITAR.INP:

Dòng đầu tiên chứa 2 số nguyên n và p,

Dòng thứ i trong n dòng sau chứa 2 số nguyên si và fi.

Kết quả: Đưa ra file văn bản GUITAR.OUT một số nguyên – số thao tác bấm phím ít nhất

cần thực hiện.

Ví dụ:

GUITAR.INP GUITAR.OUT 5 15

2 8

2 10

2 12

2 10

2 5

7

e11 Cr7 3

Page 32: ĐỊNH HƢỚNG CHUYÊN MÔN o b ng h ọc A ĐỊNH HƢỚNGchuyenlequydonlaichau.edu.vn/upload/32237/20190808/P_He_2011.pdf · Việc đào tạo, bồi dưỡng học sinh giỏi

32/64

C++ #include <fstream>

using namespace std;

int main()

{long n,p,s,f,k,r;

ifstream fi ("GUITAR.INP");

ofstream fo ("GUITAR.OUT");

fi>>n>>p;

{long a[6][p];

for (int i=0; i<6;i++) a[i][0]=0;

r=0; k=0;

for (int i=1; i<=n;i++)

{ fi>>s>>f; --s;

while (a[s][k]>f)

{ --k; ++r;}

if (a[s][k]<f) { ++k; a[s][k]=f; ++r;}

}

}

fo<<r;

fi.close(); fo.close();

}

PASCAL Program GUITAR;

Const tfi='GUITAR.INP';

tfo='GUITAR.OUT';

var m,n,p,k,s,f,i,r:longint;

a:array[1..6,0..300000] of integer;

fi,fo:text;

BEGIN

assign(fi,tfi); reset(fi);

readln(fi,n,p);

r:=0; k:=0;

for i:=1 to 6 do a[i,0]:=0;

for i :=1 to n do

begin

readln(fi,s,f);

while a[s,k]>f do begin dec(k); inc(r) end;

if a[s,k]<f then begin inc(k);a[s,k]:=f; inc(r)

end

end;

assign(fo,tfo); rewrite(fo);

writeln(fo,r);

close(fi); close(fo)

END.

Page 33: ĐỊNH HƢỚNG CHUYÊN MÔN o b ng h ọc A ĐỊNH HƢỚNGchuyenlequydonlaichau.edu.vn/upload/32237/20190808/P_He_2011.pdf · Việc đào tạo, bồi dưỡng học sinh giỏi

33/64

Ô MÀU VÀNG Tên chương trình: YELLOW.???

Phòng ngủ của Gholam được lát bằng các viên gạch men vuông màu vàng và trắng kẻ ca rô.

Mỗi khi buồn chán Gholam đứng ở một viên gạch màu trắng nào đó, quay mặt sang phải

hoặc sang trái, nghĩ trong đầu một số nguyên n rồi đi thẳng theo hàng đó n bước, mỗi bước

Gholam chuyển sang viên gạch kề ở

cùng hàng, nếu chạm tường thì quay

1800 và tiếp tục thực hiện các bước đi,

vừa đi vừa đếm số lần mình đặt chân

lên viên gạch màu vàng. Các viên

gạch trong hàng mà Gholam đứng

được đánh số từ 1 đến m từ trái qua

phải. Ví dụ, m = 6, màu các viên gạch từ trái qua phải là Y, W, W, Y, W, Y (Y – màu vàng, W –

màu trắng), Gholam đứng ở viên gạch số 3, đi 7 bước với hướng ban đầu là sang phải, trong

trường hợp này Gholam sẽ dừng lại ở viên số 2 và có 3 lần bước lên viên gạch màu vàng.

Dữ liệu: Vào từ file văn bản YELLOW.INP:

Dòng đầu tiên chứa số nguyên t – số lượng tests trong file,

Mỗi test cho trên 2 dòng:

o Dòng đầu tiên chứa 2 số nguyên m và n (3 ≤ m ≤ 100, 1 ≤ n ≤ 1 000),

o Dòng thứ 2 chứa m số nguyên a1, a2, . . ., am, ai = 0 ứng với viên màu vàng,

ai > 0 ứng với viên màu trắng, ai = 2 có nghĩa là Gholam đang đứng ở viên

thứ i và quay mặt về bên phải (nhìn xuống cuối hàng), ai = 3 xác định

Gholam đang đứng ở viên thứ i và quay mặt về bên trái (nhìn về đầu hàng

ghạch). Dữ liệu đảm bảo chỉ có một ai > 1.

Kết quả: Đưa ra file văn bản YELLOW.OUT, kết quả mỗi test đưa ra trên một dòng dưới

dạng số nguyên – số lần bước trên viên gạch màu vàng.

Ví dụ:

YELLOW.INP YELLOW.OUT 2

6 7

0 1 2 0 1 0

5 3

0 3 1 0 0

3

1

Page 34: ĐỊNH HƢỚNG CHUYÊN MÔN o b ng h ọc A ĐỊNH HƢỚNGchuyenlequydonlaichau.edu.vn/upload/32237/20190808/P_He_2011.pdf · Việc đào tạo, bồi dưỡng học sinh giỏi

34/64

C++ #include <fstream>

using namespace std;

ifstream fi ("yellow.inp");

ofstream fo ("yellow.out");

int r;

void xly()

{int m,n,r,t0,t1,d,id,m2,p,q;

fi>>m>>n;

{int a[3*m-2];

t0=0;t1=0;m2=2*m-2;

for (int i=m-1;i<2*m-1;i++)

{fi>>a[i];

switch (a[i])

{case 0: t0++; break;

case 1: t1++; break;

case 2:case 3: d=a[i]; id=i; a[i]=0;break;

}

}

for (int i=0;i<m-1;i++) a[i]=a[2*m-2-i];

for (int i=0;i<m-1;i++) a[i+2*m-1]=a[2*m-3-i];

t1*=2; t-=(a[m-1]+a[2*m-2]);

p=n/m2; q=n%m2;

r=t1*p;

if (d==2) for(int i=1; i<=q;i++) r+=a[i+id];

else for (int i=1;i<=q;i++) r+=a[id-i];

fo<<r<<endl;

}

}

int main()

{int t;

fi>>t;

for (int i =1;i<=t;i++) xly();

fi.close(); fo.close();

}

Page 35: ĐỊNH HƢỚNG CHUYÊN MÔN o b ng h ọc A ĐỊNH HƢỚNGchuyenlequydonlaichau.edu.vn/upload/32237/20190808/P_He_2011.pdf · Việc đào tạo, bồi dưỡng học sinh giỏi

35/64

PASCAL Program YELLOW;

Const tfi='YELLOW.INP';

tfo='YELLOW.OUT';

var t,m,n,p,q,t1,m2,i,r,d,id:longint;

a:array[-99..199] of integer;

fi,fo:text;

Procedure xly;

var i:integer;

Begin

readln(fi,m,n); t1:=0; m2:=2*m-2;

for i:=1 to m do

begin

read(fi,a[i]);

case a[i] of

1:inc(t1);

2,3:begin id:=i;d:=a[i];a[i]:=0 end

end

end;

for i:=2 to m do a[2-i]:=a[i];

for i:=2 to m do a[m+i-1]:= a[m-i+1];

t1:=t1*2-a[1]-a[m];

p:=n div m2; q:=n mod m2;

r:=t1*p;

if d=2 then for i:=id to id+q do r:=r+a[i]

else for i:=id downto id-q do r:=r+a[i];

writeln(fo,r)

End;

Page 36: ĐỊNH HƢỚNG CHUYÊN MÔN o b ng h ọc A ĐỊNH HƢỚNGchuyenlequydonlaichau.edu.vn/upload/32237/20190808/P_He_2011.pdf · Việc đào tạo, bồi dưỡng học sinh giỏi

36/64

TI VI Tên chương trình: TV.???

Người ta tiến hành điều tra thống kê tình hình xem ti vi trong dân chúng. Mỗi người trong số

n người được hỏi yêu cầu cho biết thời điểm người ta bắt đầu xem ti vi và thời điểm mà hết

cuối giây đó người ta rời khỏi ti vi. Câu trả lời được ghi lại dưới dạng:

HH:MM:SS – HH:MM:SS

Trong đó 0 ≤ HH ≤ 23, 0 ≤ MM, SS ≤ 59. Hai thời điểm đầu và cuối có thể không cùng một

ngày, ví dụ, một người có thể bắt đầu xem từ 23:45:30 cho đến 01:15:00 sáng ngày hôm sau.

Dĩ nhiên, không ai xem ti vi liên tục cả một ngày.

Sau khi đã có đủ dữ liệu, các nhà thống kê bắt đầu phân tích.

Độ phổ biến của một giây nào đó được tính bằng tổng số người có xem ti vi ở giây đó. Độ

phổ biến của một khoảng thời gian được tính bằng tổng độ phổ biến của các giây trong

khoảng đó chia cho tổng số giây trong khoảng.

Hãy tính độ phổ biến của mỗi khoảng trong số q khoảng cho trước mà các nhà thống kê quan

tâm.

Dữ liệu: Vào từ file văn bản TV.INP:

Dòng đầu tiên chứa số nguyên n (1 ≤ n ≤ 105),

Mỗi dòng trong n dòng sau chứa một câu trả lời của người được hỏi,

Dòng thứ n+2 chứa số nguyên q (1 ≤ q ≤ 105),

Mỗi dòng trong q dòng sau chứa một khoảng thời gian thống kê, ghi theo quy cách

như câu trả lời khi điều tra.

Kết quả: Đưa ra file văn bản TV.OUT, kết quả ứng với mỗi khoảng thống kê đưa ra trên một

dòng dưới dạng số thực độ chính xác không ít hơn 10-6

.

Ví dụ:

TV.INP TV.OUT 5

00:00:00 - 00:00:01

00:00:01 - 00:00:03

00:00:00 - 00:00:02

00:00:05 - 00:00:09

00:00:06 - 00:00:06

5

00:00:00 - 00:00:03

00:00:07 - 00:00:09

00:00:06 - 00:00:06

00:00:05 - 00:00:09

00:00:00 - 00:00:09

2.0000000000

1.0000000000

2.0000000000

1.2000000000

1.4000000000

e25 Cr11 2

C++

Thời điểm bắt đầu Thời điểm cuối

Page 37: ĐỊNH HƢỚNG CHUYÊN MÔN o b ng h ọc A ĐỊNH HƢỚNGchuyenlequydonlaichau.edu.vn/upload/32237/20190808/P_He_2011.pdf · Việc đào tạo, bồi dưỡng học sinh giỏi

37/64

#include <fstream>

#include <string>

#include <iomanip>

using namespace std;

long n,q,b[86400],tb,te;

string s;

ifstream fi ("TV.INP");

ofstream fo ("TV.OUT");

void nhapdl()

{ s.reserve(19);

getline(fi,s);

tb=(((s[0]-48)*10+s[1]-48)*60+(s[3]-48)*10+s[4]-48)*60+(s[6]-

48)*10+s[7]-48;

te=(((s[11]-48)*10+s[12]-48)*60+(s[14]-48)*10+s[15]-48)*60+(s[17]-

48)*10+s[18]-48;

}

void gn_be()

{b[tb]++;

if (te==86399) return;

if (te<tb)b[0]++;

b[++te]--;

}

void tichluy()

{long t;

t=b[0];

for (int i=1;i<86400;i++)

{ t+=b[i];

b[i]=(b[i-1]+t);

}

}

float xd_r()

{ float x;

x=b[te];

if (tb==0) return(x);

if (tb<=te) return(x-b[tb-1]);

return(x+b[86399]-b[tb-1]);

}

void xd_kq()

{float r,d;

if (tb>te) d=86400-tb+te+1; else d=te-tb+1;

r= xd_r()/d;

fo<<setprecision(8)<<r<<endl;

}

int main()

{memset(b,0,sizeof(b));

fi>>n; getline(fi,s);

for (int i=1;i<=n;i++)

{nhapdl();

gn_be();

}

tichluy();

fi>>q; getline(fi,s);

Page 38: ĐỊNH HƢỚNG CHUYÊN MÔN o b ng h ọc A ĐỊNH HƢỚNGchuyenlequydonlaichau.edu.vn/upload/32237/20190808/P_He_2011.pdf · Việc đào tạo, bồi dưỡng học sinh giỏi

38/64

for (int i=1;i<=q;i++)

{nhapdl();

xd_kq();

}

fi.close(); fo.close();

}

ĐƢỜNG GẤP KHÚC Tên chương trình: POLYGON.???

Trên lưới ô vuông vô hạn với tọa độ các đỉnh nút là nguyên người ta cho một đường gấp khúc

đơn khép kín n đỉnh, tức là đường gấp khúc mà 2 cạnh liên tiếp chỉ có một điểm chung ở

đỉnh, một cạnh không cắt các cạnh khác và cũng

không có điểm chung nào khác. Đỉnh của đường gấp

khúc trùng với điểm chia của lưới.

Hãy tính tổng độ dài các đoạn thẳng của lưới nằm gọn

trong đa giác giới hạn bởi đường gấp khúc.

Dữ liệu: Vào từ file văn bản POLYGON.INP:

Dòng đầu tiên chứa số nguyên n (3 ≤ n ≤

105),

Dòng thứ i trong n dòng sau chứa 2 số nguyên

xi và yi – tọa độ đỉnh i (|xi|, |yi| ≤ 5×108).

Tọa độ các đỉnh cho theo một chiều nào đó

(cùng hoặc ngược chiều kim đồng hồ).

Kết quả: Đưa ra file văn bản POLYGON.OUT một số

thực L – tổng độ dài tìm được. Gọi R là độ dài chính

xác. Kết quả được coi là đúng nếu thỏa mãn một trong 2 điều kiện sau:

|L-R| ≤ R×10-6

(sai số tương đối),

|L-R| ≤ 10-6

(sai số tuyệt đối).

Ví dụ:

POLYGON.INP POLYGON.OUT 5

0 0

-2 2

-2 -1

2 -2

2 0

12.5

Page 39: ĐỊNH HƢỚNG CHUYÊN MÔN o b ng h ọc A ĐỊNH HƢỚNGchuyenlequydonlaichau.edu.vn/upload/32237/20190808/P_He_2011.pdf · Việc đào tạo, bồi dưỡng học sinh giỏi

39/64

Giải thuật

Đa giác có thể chia thành các hình thang có cạnh song song với trục Oy, chiều cao bàng 1 (có

thể có hình thang suy biến thành tam giác),

Các đoạn thẳng của lưới, song song với trục Oy và nằm gọn trong đa giác, tham gia vào quá

trình tính diện tích 2 lần: một lần là

đáy dưới và lần khác - là đáy trên.

Các đoạn thẳng của lưới, song song

với trục Oy và nằm đường biên –

tham gia một lần.

Có nhận xét tương tự như vậy với các

đoạn của lưới, song song với trục Ox

và nằm gọn trong đa giác.

Gọi S là diện tích đa giác, lv – tổng

độ dài các đoạn biên song song với

Oy, lh – tổng độ dài các đoạn biên song song với Ox, r là kết quả cần tìm,ta có:

2r = s – 2

lv + s –

2

lh,

trong đó s = |)(|2

11

1

1 ii

n

i

ii yxyx

, xi+1 = x1, yi+1 = y1.

Page 40: ĐỊNH HƢỚNG CHUYÊN MÔN o b ng h ọc A ĐỊNH HƢỚNGchuyenlequydonlaichau.edu.vn/upload/32237/20190808/P_He_2011.pdf · Việc đào tạo, bồi dưỡng học sinh giỏi

40/64

C++

#include <iostream>

#include <fstream>

#include <cmath>

using namespace std;

int n, lh = 0, lv = 0, S = 0, x[100100],

y[100100];

ifstream fi ("POLYGON.INP");

ofstream fo ("POLYGON.OUT");

void input(){

fi>>n;

for (int i = 1; i <= n; i++) fi>>x[i]>>y[i];

x[n+1] = x[1];

y[n+1] = y[1];

}

void cal_area(){

for (int i = 1; i <= n; i++)

S += x[i]*y[i+1] - y[i]*x[i+1];

S = abs(S);

}

void cal_lh_lv(){

for (int i = 1; i <= n; i++){

if (x[i] == x[i+1])

lv += abs(y[i+1] - y[i]);

if (y[i] == y[i+1])

lh += abs(x[i+1] - x[i]);

}

}

void output(){

fo << double(2*abs(S) - lv - lh) / double(2);

}

int main(){

input();

cal_area();

cal_lh_lv();

output();

return 0;

}

Page 41: ĐỊNH HƢỚNG CHUYÊN MÔN o b ng h ọc A ĐỊNH HƢỚNGchuyenlequydonlaichau.edu.vn/upload/32237/20190808/P_He_2011.pdf · Việc đào tạo, bồi dưỡng học sinh giỏi

41/64

C++ Vào ra theo quy cách

#include <iostream>

#include <cmath>

using namespace std;

int n, lh = 0, lv = 0, S = 0, x[100100], y[100100];

void input(){

scanf("%d", &n);

for (int i = 1; i <= n; i++)

scanf("%d %d", &x[i], &y[i]);

x[n+1] = x[1];

y[n+1] = y[1];

}

void cal_area(){

for (int i = 1; i <= n; i++)

S += x[i]*y[i+1] - y[i]*x[i+1];

S = abs(S);

}

void cal_lh_lv(){

for (int i = 1; i <= n; i++){

if (x[i] == x[i+1])

lv += abs(y[i+1] - y[i]);

if (y[i] == y[i+1])

lh += abs(x[i+1] - x[i]);

}

}

void output(){

cout << double(2*abs(S) - lv - lh) / double(2);

}

int main(){

freopen("POLYGON.INP", "r", stdin);

freopen("POLYGON.OUT", "w" ,stdout);

input();

cal_area();

cal_lh_lv();

output();

return 0;

}

Page 42: ĐỊNH HƢỚNG CHUYÊN MÔN o b ng h ọc A ĐỊNH HƢỚNGchuyenlequydonlaichau.edu.vn/upload/32237/20190808/P_He_2011.pdf · Việc đào tạo, bồi dưỡng học sinh giỏi

42/64

QUAY CÓP Tên chương trình: PLAGIARY.???

Thí sinh tham dự Thi lập trình thế giới nộp n files lời giải f1, f2, . . ., fn. Trước khi chấm

Ban Giám khảo quyết định kiểm tra xem có trường hợp chép bài của nhau không. Người ta

lấy từng cặp 2 files, so sánh nội dung xem chúng có quá giống nhau hay không.

Nhưng số lượng files là rất lớn và không đủ thời gian so sánh tất cả các cặp files. Vì vậy,

người ta chỉ so sánh các file có kích thước gần nhau.

Cụ thể là, nếu với 2 files, kích thước file bé nhỏ hơn 90% kích thước file lớn thì sẽ không só

sánh chúng. Nói một cách khác, gọi di là kích thước file fi, người ta sẽ so sánh 2 files fi và

fj nếu di ≤ dj, di ≥ 0.9×dj, i ≠ j.

Hãy xác định số lượng cặp files cần so sánh.

Dữ liệu: Vào từ file văn bản PLAGIARY.INP:

Dòng đầu tiên chứa số nguyên n (1 ≤ n ≤ 105),

Dòng thứ 2 chứa n số nguyên d1, d2, . . ., dn (1 ≤ di ≤ 108 , i = 1 ÷ n).

Kết quả: Đưa ra file văn bản PLAGIARY.OUT một số nguyên – số lượng cặp files cần so

sánh.

Ví dụ:

PLAGIARY.INP PLAGIARY.OUT 5

1 1 1 1 1

10

Giải thuật

Sắp xếp {di} theo thứ tự tăng dần của giá trị,

Với mỗi i từ 1 đến n-1 tìm k = max{j: j>=i, di ≥ 0.9dj},

Nếu với i đã có k, với i+1 – chỉ cần tìm tiếp từ k+1 trở đi,

Với mỗi i kết quả tăng lên một lượng là k – i.

Độ phức tạp: O(nlogn).

Page 43: ĐỊNH HƢỚNG CHUYÊN MÔN o b ng h ọc A ĐỊNH HƢỚNGchuyenlequydonlaichau.edu.vn/upload/32237/20190808/P_He_2011.pdf · Việc đào tạo, bồi dưỡng học sinh giỏi

43/64

C++

#include <iostream>

#include <ctime>

using namespace std;

int n, up, res = 0, a[100100];

int main(){

freopen("PLAGIARY.INP", "r", stdin);

freopen("PLAGIARY.OUT", "w", stdout);

scanf("%d", &n);

for (int i = 0; i < n; i++)

scanf("%d", &a[i]);

sort(a, a+n);

a[n] = INT_MAX;

for (int i = 0; i < n; i++){

int j = min(n - 1, up);

while (j < n && 9*a[j] <= 10*a[i])

j++;

up = j;

res += j-i-1;

}

printf("%d", res);

return 0;

}

Page 44: ĐỊNH HƢỚNG CHUYÊN MÔN o b ng h ọc A ĐỊNH HƢỚNGchuyenlequydonlaichau.edu.vn/upload/32237/20190808/P_He_2011.pdf · Việc đào tạo, bồi dưỡng học sinh giỏi

44/64

CỬ TẠ Tên chương trình: DUMB_BELL.???

Rèn luyện thể lực bằng cách tập nâng tạ thu hút được sự chú ý của rất nhiều bạn trẻ. Tạ là

một thanh trục có gắn ở hai đầu các đĩa tạ. Bộ đĩa tạ trong phòng tập bao gồm các loại 1kg,

2kg, 5kg, 10kg, 15kg và 20kg với số lượng mỗi loại là đủ nhiều. Các đĩa tạ ở hai đầu thanh

được gắn đối xứng để đảm bảo thanh tạ được cân. Mỗi người, tùy theo thể lực của mình, lắp

các đĩa tạ để có trọng lượng phù hợp. Để điều chỉnh trọng lượng, người ta tháo các đĩa ngoài

cùng, lắp các đĩa mới vào. Do tính đối xứng của

thanh tạ, ta chỉ xét các thao tác điều chỉnh ở một

đầu.

Hiện tại ở một đầu đang có n đĩa tạ gắn vào trục (1

≤ n ≤ 10), tính từ trong ra ngoài đĩa thứ i có trọng

lượng pi. Bạn cần có thanh tạ với trọng lượng một

đầu là w (0 ≤ w ≤ 100). Ví dụ, hiện tại n = 4 và các

đĩa tạ là (2, 2, 1, 20), bạn cần điều chỉ trọng lượng

thành 14kg. Bạn sẽ phải thực hiện 3 thao tác tháo

lắp: tháo đĩa 20kg, tháo đĩa 1kg và lắp đĩa 10kg.

Yêu cầu: Cho n, pi, i=1 ÷ n, w. Hãy xác định số thao tác ít nhất cần thực hiện.

Dữ liệu: Vào từ file văn bản DUMB_BELL.INP:

Dòng đầu tiên chứa số nguyên n,

Dòng thứ 2 chứa n số nguyên p1, p2, . . ., pn,

Dòng thứ 3 chứa số nguyên w.

Kết quả: Đưa ra file văn bản DUMB_BELL.OUT một số nguyên – số thao tác ít nhất cần

thực hiện.

Ví dụ:

DUMB_BELL.INP DUMB_BELL.OUT

4

2 2 1 20

14

3

2 2 1

20

Page 45: ĐỊNH HƢỚNG CHUYÊN MÔN o b ng h ọc A ĐỊNH HƢỚNGchuyenlequydonlaichau.edu.vn/upload/32237/20190808/P_He_2011.pdf · Việc đào tạo, bồi dưỡng học sinh giỏi

45/64

C++ #include <iostream>

using namespace std;

const int b[6] = {1, 2, 5, 10, 15, 20};

int n, w, p, F, res = INT_MAX, s[11], L[201];

int main(){

freopen("DUMB_BELL.INP", "r", stdin);

freopen("DUMB_BELL.OUT", "w", stdout);

scanf("%d", &n);

for (int i = 1; i <= n; i++){

scanf("%d", &p);

s[i] = s[i-1] + p;

}

scanf("%d", &w);

L[1] = L[2] = L[5] = L[10] = L[15] = L[20] = 1;

for (int i = 1; i <= 200; i++){

if (L[i] == 1)

continue;

L[i] = INT_MAX;

for (int j = 0; j < 6 && b[j] < i; j++)

L[i] = min(L[i], L[i - b[j]] + 1);

}

for (int i = 0; i <= n; i++){

F = n-i;

if (s[i] > w)

F = INT_MAX;

else if (s[i] < w)

F += L[w - s[i]];

res = min(res, F);

}

printf("%d", res);

return 0;

}

Page 46: ĐỊNH HƢỚNG CHUYÊN MÔN o b ng h ọc A ĐỊNH HƢỚNGchuyenlequydonlaichau.edu.vn/upload/32237/20190808/P_He_2011.pdf · Việc đào tạo, bồi dưỡng học sinh giỏi

46/64

TỌA ĐỘ VÙNG Tên chương trình: REG_COOR.???

Để mau chóng tìm kiếm được các vùng và cung cấp bản đồ tương ứng cho người dùng

Google Map áp dụng cơ chế cây tứ phân. Bản đồ toàn bộ trái đất là t, được coi như một hình

vuông. Bằng các đường thẳng song song với cạnh và đi qua điểm giữa của cạnh, bản đồ ban

đầu được chia thành 4 phần bằng nhau, mỗi phần bằng

bản đồ ban đầu và ký hiệu các phần

đó là t, s, r, q theo chiều ngược kim đồng hồ, bắt đầu từ phần dưới trái. Đường dẫn truy

nhập tới các phần này sẽ là tt, ts, tr và tq. Mỗi phần nhận được lại có thể chia thành 4

phần con, đánh số như trên, đường dẫn tới phần con này sẽ có độ dài 3 và cứ như thế tiếp tục

cho đến khi đạt được mục tiêu tìm kiếm. Ví dụ, đường dẫn tới bản đồ Việt Nam là trst.

Xét bản đồ số hình vuông tọa độ góc dưới trái là (0, 0), góc trên phải là (2n, 2n) với 0 < n ≤

1000. Với điểm P tọa độ (x,y) (0 < x, y < 2n ta có thể chỉ ra

đường dẫn tới vùng nhỏ nhất chứa P như một điểm trong

(không nằm trên biên). Ví dụ, với P có tọa độ (5, 3) và n = 3,

vùng nhỏ nhất chứa P có đường dẫn là tsq.

Yêu cầu: Cho n, x, y. Hãy xác định đường đẫn tới vùng chứa

điểm (x, y).

Dữ liệu: Vào từ file văn bản REG_COOR.INP gồm một dòng

chứa 3 số nguyên n, x và y.

Kết quả: Đưa ra file văn bản REG_COOR.OUT xâu đường

dẫn.

Ví dụ:

REG_COOR.INP REG_COOR.OUT 3 5 3 tsq

tt

tq tr

tsq

Page 47: ĐỊNH HƢỚNG CHUYÊN MÔN o b ng h ọc A ĐỊNH HƢỚNGchuyenlequydonlaichau.edu.vn/upload/32237/20190808/P_He_2011.pdf · Việc đào tạo, bồi dưỡng học sinh giỏi

47/64

C++ #include <iostream>

#include <string>

using namespace std;

int n;

string x, y, res;

string div(string a, int b){

int hold = 0, s = 0;

string ans = "";

for (int i = 0; i < a.size(); i++){

hold = 10 * hold + (a[i] - '0');

s = hold / b;

hold %= b;

ans += ('0' + s);

}

while (ans[0] == '0')

ans.erase(0, 1);

return ans;

}

string binary_representation(string a){

string ans = "";

while (a.size()){

ans += ('0' + (a[a.size()-1] - '0') %

2);

a = div(a, 2);

}

for (int i = 0; i < (ans.size() >> 1); i++)

swap(ans[i], ans[ans.size()-i-1]);

while (ans.size() < n)

ans.insert(0, "0");

return ans;

}

int main(){

freopen("REG_COOR.INP", "r", stdin);

freopen("REG_COOR.OUT", "w", stdout);

cin >> n >> x >> y;

x = binary_representation(x);

y = binary_representation(y);

res = "";

for (int i = 0; i < n-1; i++){

if (x[i] == '0' && y[i] == '0')

res += 't';

else if (x[i] == '0' && y[i] == '1')

res += 'q';

else if (x[i] == '1' && y[i] == '0')

res += 's';

else if (x[i] == '1' && y[i] == '1')

res += 'r';

if (min(x.rfind("1"), y.rfind("1")) < i-1)

break;

}

cout << "t" << res;

return 0;

}

Page 48: ĐỊNH HƢỚNG CHUYÊN MÔN o b ng h ọc A ĐỊNH HƢỚNGchuyenlequydonlaichau.edu.vn/upload/32237/20190808/P_He_2011.pdf · Việc đào tạo, bồi dưỡng học sinh giỏi

48/64

BỘ TỘC Tên chương trình: CLAN.???

Có một hòn đảo rất đẹp, thu hút nhiều khách du lịch ghé thăm. Trên đảo có n người thuộc

nhiều bộ tộc sinh sống. Dân cư trên đảo rất thân thiện. Mỗi người thuộc một bộ tộc nào đó.

Trong đoàn du lịch có một nhà nhân chủng học. Tranh thủ dịp may được ghé thăm đảo ông

không bỏ phí thời gian tiến hành khảo sát. Ông gặp từng người một trên đảo với một câu hỏi

duy nhất: “Trên đảo, bộ tộc của bạn có bao nhiêu người?”. Từ kết quả khảo sát, ông đã xác

định được số bộ tộc khác nhau tồn tại trên đảo.

Ví dụ, với n = 10 và các câu trả lời là 5, 1, 2, 5, 5, 2, 5, 5, 2, 2 ta có thể suy ra là trên hòn đảo

có 4 bộ tộc khác nhau.

Yêu cầu: Cho n và các câu trả lời. Hãy xác định số bộ tộc trên đảo. Dữ liệu đảm bảo bài toán

có nghiệm.

Dữ liệu: Vào từ file văn bản CLAN.INP:

Dòng đầu tiên chứa số nguyên n (1 ≤ n ≤ 105),

Mỗi dòng trong n dòng sau chứa một số nguyên – câu trả lời nhận được.

Kết quả: Đưa ra file văn bản CLAN.OUT một số nguyên – số bộ tộc trên đảo.

Ví dụ:

CLAN.INP CLAN.OUT

10

5

1

2

5

5

2

5

5

2

2

4

C++

#include <fstream>

#include <set>

using namespace std;

int n, ans, res = 0;

set <int> a;

multiset <int> s;

int main(){

ifstream finp ("CLAN.INP");

ofstream fout ("CLAN.OUT");

finp >> n;

while (n--){

finp >> ans;

a.insert(ans);

s.insert(ans);

}

for (set <int>::iterator i = a.begin(); i !=

a.end(); i++)

res += s.count(*i) / (*i);

fout << res;

}

Page 49: ĐỊNH HƢỚNG CHUYÊN MÔN o b ng h ọc A ĐỊNH HƢỚNGchuyenlequydonlaichau.edu.vn/upload/32237/20190808/P_He_2011.pdf · Việc đào tạo, bồi dưỡng học sinh giỏi

49/64

LÂY NHIỄM Tên chương trình: INFECT.???

Steve phát hiện ra một lỗi trong hệ điều hành nỗi tiếng đang được sử dụng phổ biến. Lợi dụng

lỗi này ta có thể truy nhập và điều khiển máy tính bất kỳ đang kết nối và sử dụng hệ điều

hành này. Khi kích hoạt cơ chế tạo lỗi, nếu một máy tính đang được kết nối với đúng 8 máy

tính khác ta có một con đường riêng để tuy nhập vào nó trong đúng 8 giây.

Steve viết một chương trình virus đơn giản khai thác lỗi này. Virus hoạt động theo kiểu tuần

tự, nghĩa là máy tính bị nhiễm virus ở mỗi thời điểm chỉ tấn công sang đúng một máy khác

mà thôi.

Yêu cầu: Ban đầu Steve có 8 mấy đã bị nhiễm virus. Hãy xác định sau bao lâu virus sẽ lan

được tới tất cả n máy tính của Steve.

Dữ liệu: Vào từ file văn bản INFECT.INP gồm một dòng chứa số nguyên n (8 ≤ n ≤108).

Kết quả: Đưa ra file văn bản INFECT.OUT một số nguyên – thời gian cần thiết để các máy

đều bị nhiểm virus.

Ví dụ2:

INFECT. INP INFECT. OUT

20 80

C++ #include <fstream>

using namespace std;

int n, cur = 8, res = 0;

int main(){

ifstream finp ("INFECT.INP");

ofstream fout ("INFECT.OUT");

finp >> n;

while (cur < n){

cur += (cur / 8);

res += 8;

}

fout << res;

return 0;

}

Page 50: ĐỊNH HƢỚNG CHUYÊN MÔN o b ng h ọc A ĐỊNH HƢỚNGchuyenlequydonlaichau.edu.vn/upload/32237/20190808/P_He_2011.pdf · Việc đào tạo, bồi dưỡng học sinh giỏi

50/64

MẬT KHẨU Tên chương trình: PASSW.???

Để có được một mật khẩu có độ an toàn cao cần phải khéo léo trong cách chọn. Người ta

thường hay dùng các mật khẩu đơn giản, dễ nhớ. Nhưng những mật khẩu đó không có độ an

toàn cao. Cần phải có một chiến lược chọn mật khẩu.

Xét chiến lược chọn mật khẩu sau:

Mật khẩu phải có độ dài ít nhất 6 ký tự,

Trong mật khẩu phải bao gồm các ký tự 3 loại:

o Chữ cái latinh in hoa,

o Chữ cái latinh thường,

o Chữ số hệ 10.

Yêu cầu: Cho xâu S độ dài không quá 105 và chỉ chứa các ký tự thuộc 3 loại dã nêu ở

trên.Hãy xác định độ dài của xâu con ngắn nhất các ký tự liên tiếp nhau có thể sử dụng làm

mật khẩu theo chiến lược đã nêu. Nếu không tồn tại xâu con thỏa mãn thì đưa ra kết quả độ

dài 0.

Dữ liệu: Vào từ file văn bản PASSW.INP:

Dòng đầu tiên chứa số nguyên n – số lượng tests (1 ≤ n ≤ 50),

Mỗi dòng trong n dòng sau chứa một xâu S.

Kết quả: Đưa ra file văn bản PASSW.OUT n số nguyên, mỗi số trên một dòng, dòng i tương

ứng với kết quả test thứ i.

Ví dụ:

PASSW.INP PASSW.OUT

4

AliKam123test

AbCdEfG

88syadneerG

Windows7released21october2009

6

0

10

8

Page 51: ĐỊNH HƢỚNG CHUYÊN MÔN o b ng h ọc A ĐỊNH HƢỚNGchuyenlequydonlaichau.edu.vn/upload/32237/20190808/P_He_2011.pdf · Việc đào tạo, bồi dưỡng học sinh giỏi

51/64

C++ #include <fstream>

#include <string>

using namespace std;

int n;

int main(){

ifstream finp ("PASSW.INP");

ofstream fout ("PASSW.OUT");

finp >> n;

while (n--){

string s;

finp >> s;

if (s.size() < 6){

fout << "0" << endl;

continue;

}

int upper = -1 , lower = -1, num = -1, res = INT_MAX;

for (int i = 0; i <= s.size(); i++){

if ('A' <= s[i] && s[i] <= 'Z')

upper = i;

else if ('a' <= s[i] && s[i] <= 'z')

lower = i;

else if ('0' <= s[i] && s[i] <= '9')

num = i;

if (upper >= 0 && lower >= 0 && num >=0)

res = min(res, i - min(min(upper, lower), num) + 1);

}

if (upper == -1 || lower == -1 || num == -1)

fout << "0" << endl;

else

fout << max(res, 6) << endl;

}

return 0;

}

Page 52: ĐỊNH HƢỚNG CHUYÊN MÔN o b ng h ọc A ĐỊNH HƢỚNGchuyenlequydonlaichau.edu.vn/upload/32237/20190808/P_He_2011.pdf · Việc đào tạo, bồi dưỡng học sinh giỏi

52/64

TRỢ GIÚP ĐĂNG NHẬP Tên chương trình: F1LOGIN.???

Cuối cùng thì một hệ thống chấm điểm mới cũng đã được đưa vào sử dụng. Mật khẩu để truy

cập phải khác rỗng, có độ dài không quá 10 ký tự bao gồm chữ số, chữ cái la tinh thường và

hoa. Mô đun đăng nhập, ngoài việc kiểm tra mật khẩu còn giúp người sử dụng phát hiện hai

loại sai sót thường gặp:

Đặt chế độ phím CAPLOCK ở chế độ ON, khi đó chữ hoa có thể thành chữ thường và

ngược lại,

Đặt phím NUMLOCK ở chế độ OFF, khi đó các ký tự số sẽ bị bỏ qua.

Chương trình sẽ so sánh mật khẩu đã đăng ký với mật khẩu nhập vào. Nếu 2 mật khẩu trùng

khớp với nhau thì đưa ra thông báo “Login successful.”. Nếu ở mật khẩu nhập vào,

thãy mỗi chữ cái hoa thành chữ cái thường tương ứng và thay mỗi chữ cái thường thành chữ

cái hoa tương ứng sẽ được mật khẩu đúng, khi đó chương trình đưa ra thông báo ”Wrong

password. Please, check your caps lock key.” Nếu trong mật khẩu hệ

thống lưu trữ bỏ tất cả các ký tự số, kết quả trùng khớp với xâu người sử dụng nhập thì đưa ra

thông báo “Wrong password. Please, check your num lock key.” Nếu

trong mật khẩu hệ thống lưu trữ bỏ tất cả các ký tự số và đổi chữ hoa thành chữ thường, chữ

thường thành chữ hoa, kết quả trùng khớp với xâu người sử dụng nhập thì đưa ra thông báo

“Wrong password. Please, check your caps lock and num lock

key.” Trong các trường hợp còn lại – đưa ra thông báo “Wrong password.”.

Dữ liệu: Vào từ file văn bản F1LOGIN.INP:

Dòng đầu tiên chứa số nguyên t – số lượng tests,

Mỗi dòng trong t dòng tiếp theo chứa s xâu cách nhau bởi dấu cách: mật khẫu lưu trữ

và mật khẩu nhập vào.

Kết quả: Đưa ra file văn bản F1LOGIN.OUT các thông báo tương ứng với từng cặp mật

khẩu, mỗi thông báo trên một dòng.

Ví dụ:

F1LOGIN.INP F1LOGIN.OUT 6

aaBBccDD aaBBccDD

aaBBccDD aaBBccDD9

aaBBccDD aaBBCCDD

aaBBccDD AAbbCCdd

a4B3c2D1 aBcD

a4B3c2D1 AbCd

Login successful Wrong password. Wrong password. Wrong password. Please, check your caps lock key.

Wrong password. Please, check your num lock key.

Wrong password. Please, check your caps lock and num lock key.

Page 53: ĐỊNH HƢỚNG CHUYÊN MÔN o b ng h ọc A ĐỊNH HƢỚNGchuyenlequydonlaichau.edu.vn/upload/32237/20190808/P_He_2011.pdf · Việc đào tạo, bồi dưỡng học sinh giỏi

53/64

C++ #include <iostream>

#include <string>

using namespace std;

int n;

int main(){

freopen("F1LOGIN.INP", "r", stdin);

freopen("F1LOGIN.OUT", "w", stdout);

cin >> n;

while (n--){

string s,t;

cin >> s >> t;

if (s.compare(t) == 0){

cout << "Login successful. " << endl;

continue;

}

cout << "Wrong password. ";

string ss = s, tt = t;

bool stop;

while (true){

stop = true;

for (int i = 0; i < ss.size(); i++)

if ('0' <= ss[i] && ss[i] <= '9'){

ss.erase(i, 1);

stop = false;

}

if (stop)

break;

}

for (int i = 0; i < tt.size(); i++)

if ('a' <= tt[i] && tt[i] <= 'z')

tt[i] -= ('a' - 'A');

else if ('A' <= tt[i] && tt[i] <= 'Z')

tt[i] += ('a' - 'A');

bool cap = ((s.compare(tt) == 0) || (ss.compare(tt) == 0)),

num = (ss.size() < s.size() && ((ss.compare(t) == 0) ||

(ss.compare(tt) == 0)));

if (cap && num)

cout << "Please, check your caps lock and num lock key."

<< endl;

else if (cap && !num)

cout << "Please, check your caps lock key." << endl;

else if (!cap && num)

cout << "Please, check your num lock key." << endl;

else

cout << endl;

}

return 0;

}

Page 54: ĐỊNH HƢỚNG CHUYÊN MÔN o b ng h ọc A ĐỊNH HƢỚNGchuyenlequydonlaichau.edu.vn/upload/32237/20190808/P_He_2011.pdf · Việc đào tạo, bồi dưỡng học sinh giỏi

54/64

XÓA 7 Tên chương trình: DROP7.???

Xóa 7 là trò chơi một người. Cho lưới ô vuông kích thước 7×7, các cột được đánh số từ 1 đến

7 từ trái sang phải. Ban đầu lưới ô vuông rỗng. Ở mỗi lượt đi sẽ có một viên bi rơi xuống từ

trên cột i. Viên bi được đánh một trong các số từ 1 đến 7. Ở đây chúng ta chỉ xem xét việc xử

lý bảng khi viên bi rơi xuống cột i. Viên

bi sẽ rơi xuống đáy cột i nếu cột này

rỗng hoặc dừng lại khi chạm viên bi trên

cùng trong cột. Mỗi viên bi chiếm đúng 1

ô.

Ví dụ, nếu ta thả viên bi 3 ở cột 1 nó sẽ

dừng lại trên viên bi 6, nếu thả nó ở cột

3, nó sẽ dừng lại ở đáy, còn nếu thả ở cột

7 – dừng trên viên bi 5. Các viên bi trong

một cột tạo thành nhóm cột. Dãy các viên

bi kề nhau trong một hàng hai đầu của

dãy là ô trống hoặc biên của lưới tạo

thành một nhóm hàng. Số lượng bi trong

nhóm gọi kích thước của nhóm. Nếu có

một hoặc một vài viên bi trong nhóm có

số đúng bằng kích thước của nhóm thì

những viên bi đó sẽ bị bốc hơi, biến mất

khỏi bảng, những ô chứa các viên bi này

sẽ trở thành ô trống và các viên bi còn lại (nếu có) trong cột sẽ rơi xuống dưới, lấp vào các ô

trống.

Ví dụ, nếu viên bi 3 được thả vào cột 4, nó sẽ tạo thành một nhóm cột kích thước 3 và nó sẽ

bị bốc hơi. Nếu thả nó vào cột 7, một nhóm cột kích thước 3 cũng sẽ hình thành, các viên bi ở

dòng 1 và 3 sẽ bị bốc hơi và viên bi 4 sẽ rơi xuống đáy. Việc các viên bi bốc hơi làm thay

đổi cấu hình bi trong bảng, hình thành những nhóm hàng, nhóm cột mới và lại có thể làm một

số viên bi nào đó khác bốc hơi!

Cho bảng rỗng ban đầu. Xét n viên bi lần lượt rơi xuống, viên bi thứ i có số là vi rơi xuống

cột ci. Hãy đưa ra trạng thái cuối cùng của bảng dưới ma trận 7×7 ký tự (7 xâu độ dài 7), ký

tự “#” chỉ ô trống, ký tự số chỉ số hiệu của viên bi tại ô đó. Nếu ở một thời điểm nào đó, một

cột đã đầy mà vẫn có bi rơi xuống cột đó thì đưa ra thông báo “Game Over!”.

Dữ liệu: Vào từ file văn bản DROP7.INP gồm nhiều tests, mỗi test cho trên một nhóm dòng,

dòng đầu tiên trong nhóm chứa số nguyên n (1 ≤ n ≤ 1000), dòng thứ i trong n dòng tiếp

theo chứa 2 số nguyên vi và ci. File dữ liệu kết thúc bằng dòng chứa một số 0.

Kết quả: Đưa ra file văn bản DROP7.OUT, kết quả mỗi test được đưa ra dưới dạng 7 dòng,

mỗi dòng một xâu độ dài 7 hoặc đưa ra 1 dòng thông báo “Game Over!”. Giữa kết quả của

2 tests liên tiếp nhau là một dòng trống.

6 5

5

4

7

7

5

5

6

6

6

3

3

Nhóm cột

Nhómhàng

1 2 3 4 5 6 7

Page 55: ĐỊNH HƢỚNG CHUYÊN MÔN o b ng h ọc A ĐỊNH HƢỚNGchuyenlequydonlaichau.edu.vn/upload/32237/20190808/P_He_2011.pdf · Việc đào tạo, bồi dưỡng học sinh giỏi

55/64

Ví dụ:

DROP7.INP DROP7.OUT 6

2 2

3 2

6 2

4 3

1 1

6 7

11

5 3

5 3

2 3

2 3

2 3

3 3

4 3

5 3

6 3

7 3

1 3

0

#######

#######

#######

#######

#######

#######

#64###6

Game Over!

Page 56: ĐỊNH HƢỚNG CHUYÊN MÔN o b ng h ọc A ĐỊNH HƢỚNGchuyenlequydonlaichau.edu.vn/upload/32237/20190808/P_He_2011.pdf · Việc đào tạo, bồi dưỡng học sinh giỏi

56/64

C++

#include <iostream>

using namespace std;

int n, a[10][10], top[10];

bool find(){

for (int col = 1; col <= 7; col++)

for (int i = 1; i <= 7; i++)

if (top[col] > 0 && a[col][i] == top[col])

return true;

for (int row = 1; row <= 7; row++){

int i = 1;

while (i <= 7){

while (i <= 7 && a[i][row] == 0)

i++;

int j = i;

while (a[j+1][row])

j++;

for (int k = i; k <= j; k++)

if (j > i && a[k][row] == j-i+1)

return true;

i = j+1;

}

}

return false;

}

void del_column(int col){

if (top[col] == 0)

return;

int num_del = 0;

for (int i = 1; i <= 7; i++)

if (a[col][i] == top[col]){

a[col][i] = 0;

num_del++;

}

top[col] -= num_del;

}

void del_row(int row){

int i = 1;

while (i <= 7){

while (i <= 7 && a[i][row] == 0)

i++;

int j = i;

while (a[j+1][row])

j++;

for (int k = i; k <= j; k++)

if (j > i && a[k][row] == j-i+1){

a[k][row] = 0;

top[k]--;

}

i = j+1;

}

}

Page 57: ĐỊNH HƢỚNG CHUYÊN MÔN o b ng h ọc A ĐỊNH HƢỚNGchuyenlequydonlaichau.edu.vn/upload/32237/20190808/P_He_2011.pdf · Việc đào tạo, bồi dưỡng học sinh giỏi

57/64

void drop_column(int col){

int num = 0, temp[10];

memset(temp, 0, sizeof(temp));

for (int i = 1; i <= 7; i++)

if (a[col][i]){

temp[++num] = a[col][i];

a[col][i] = 0;

}

for (int i = 1; i <= num; i++)

a[col][i] = temp[i];

}

int main(){

freopen("DROP7.INP", "r", stdin);

freopen("DROP7.OUT", "w", stdout);

while (true){

scanf("%d", &n);

if (n == 0)

break;

memset(a, 0 , sizeof(a));

memset(top, 0, sizeof(top));

int val, col;

bool game_over = false;

while (n--){

scanf("%d %d", &val, &col);

if (top[col] == 7)

game_over = true;

a[col][++top[col]] = val;

while (find()){

for (int col = 1; col <= 7; col++)

del_column(col);

for (int row = 1; row <= 7; row++)

del_row(row);

for (int col = 1; col <= 7; col++)

drop_column(col);

}

}

if (game_over){

printf("Game Over!\n");

continue;

}

for (int row = 7; row >= 1; row--){

for (int col = 1; col <= 7; col++)

if (a[col][row] == 0)

printf("#");

else

printf("%d", a[col][row]);

printf("\n");

}

printf("\n");

}

return 0;

}

Page 58: ĐỊNH HƢỚNG CHUYÊN MÔN o b ng h ọc A ĐỊNH HƢỚNGchuyenlequydonlaichau.edu.vn/upload/32237/20190808/P_He_2011.pdf · Việc đào tạo, bồi dưỡng học sinh giỏi

58/64

BĂNG GIẤY Tên chương trình: STRIP.PAS

Xét băng giấy có độ dài 2K ô và độ rộng một ô. Các ô dược đánh số từ trái sang phải, bắt đầu từ 1.

Người ta gập đôi băng giấy sao cho các ô đầu tiên nằm ở lớp dưới. Như vậy băng giấy trở thành hai

lớp và độ dài còn một nửa. Người ta cứ gập đôi như vậy cho đến khi nó có 2K lớp.

Yêu cầu: Cho K và N (1 ≤ K ≤ 30, 1 ≤ N ≤ 2 000 000 000), hãy xác định ô thứ N nằm ở lớp thứ mấy

từ dưới lên.

Dữ liệu: Vào từ file văn bản STRIP.INP chứa 2 số nguyên K và N.

Kết quả: Đưa ra file văn bản STRIP.OUT số thứ tự tìm được hoặc giá trị -1 nếu băng giấy

không có ô N.

Ví dụ:

STRIP.INP STRIP.OUT

4 3 9

Page 59: ĐỊNH HƢỚNG CHUYÊN MÔN o b ng h ọc A ĐỊNH HƢỚNGchuyenlequydonlaichau.edu.vn/upload/32237/20190808/P_He_2011.pdf · Việc đào tạo, bồi dưỡng học sinh giỏi

59/64

C++ #include <fstream>

#include <string>

using namespace std;

int n, k, kk, p = 1, q;

string s;

ifstream fi ("STRIP.INP");

ofstream fo ("STRIP.OUT");

inline void input(){fi >> k >> n;}

inline void initial(){k--; n--; s = "";}

inline void generate_s(){

while (k>=0){

if (((n >> k) & 1) == 0)

s += 'D';

else{

s += 'U';

n = ~n;

}

k--;

}

}

inline void process(){

for (int i = 0; i < s.size(); i++){

if (s[i] == 'U'){

int temp = p;

p = p+(q << 1)+1;

q = temp-1;

}

else

q += p+q;

}

}

inline void output(){

fo << p;

}

int main(){

input();

initial();

generate_s();

process();

output();

return 0;

}

Page 60: ĐỊNH HƢỚNG CHUYÊN MÔN o b ng h ọc A ĐỊNH HƢỚNGchuyenlequydonlaichau.edu.vn/upload/32237/20190808/P_He_2011.pdf · Việc đào tạo, bồi dưỡng học sinh giỏi

60/64

ĐƢỜNG VIỀN Tên chương trình: CONTOUR.???

Một khu công nghiệp được giới hạn bởi đường gấp khúc khép kín không tự cắt n đỉnh có các

cạnh song song với trục tọa độ (4 ≤ n ≤ 105). Đỉnh thứ i của đường gấp khúc có tọa độ

nguyên (xi, yi), giá trị tuyệt đối của các tọa độ không vượt quá 109.

Người ta làm một con đường chạy dọc theo biên của khu công nghiệp với độ rộng của đường

là d (d nguyên, 0 < d < 1000). Mỗi đoạn thẳng của đường có một cạnh là đường biên của

khu công nghiệp, cạnh kia là đường song song

và nằm ngoài khu công nghiệp. Các cạnh này

tạo thành một hình bao lấy khu công nghiệp.

Hãy xác định tọa độ đỉnh của hình bao.

Dữ liệu: Vào từ file văn bản CONTOUR.INP:

Dòng đầu tiên chứa 2 số nguyên n và d,

Dòng thứ i trong n dòng sau chứa 2 số

nguyên xi và yi.

Tọa độ các đỉnh được cho theo một chiều nào

đó. Dữ liệu đảm bảo tồn tại hình bao.

Kết quả: Đưa ra file văn bản CONTOUR.OUT n dòng, dòng thứ i chứa 2 số nguyên xác định

tọa độ đỉnh thứ i của hình bao. Tọa độ các đỉnh được đưa ra theo chiều ngược kim đồng hồ,

bắt đầu từ đỉnh cao nhất và trái nhất.

Ví dụ:

CONTOUR.INP CONTOUR.OUT 6 1

5 -1

5 5

2 5

2 2

-2 2

-2 -1

1 6

1 3

3 -3

-3 -2

6 -2

6 6

Page 61: ĐỊNH HƢỚNG CHUYÊN MÔN o b ng h ọc A ĐỊNH HƢỚNGchuyenlequydonlaichau.edu.vn/upload/32237/20190808/P_He_2011.pdf · Việc đào tạo, bồi dưỡng học sinh giỏi

61/64

C++ #include <iostream>

using namespace std;

int n, d, first = 100009, x[100010], y[100010], res_x[100010], res_y[100010];

bool clockwise;

void input(){

cin >> n >> d;

for (int i = 1; i <= n; i++)

cin >> x[i] >> y[i];

x[n+1] = x[1];

y[n+1] = y[1];

x[0] = x[n];

y[0] = y[n];

}

void define_direction(){

int S = 0;

for (int i = 1; i <= n; i++)

S += x[i]*y[i+1] - y[i]*x[i+1];

clockwise = (S < 0);

}

void process(){

y[first] = -INT_MAX;

x[first] = INT_MAX;

for (int i = 1; i <= n; i++){

if (x[i] == x[i-1]){

if (y[i] > y[i-1])

res_y[i] = y[i] + d;

else

res_y[i] = y[i] - d;

if (x[i] < x[i+1])

res_x[i] = x[i] - d;

else

res_x[i] = x[i] + d;

}

else{// x[i] == x[i+1]

if (y[i] > y[i+1])

res_y[i] = y[i] + d;

else

res_y[i] = y[i] - d;

if (x[i] < x[i-1])

res_x[i] = x[i] - d;

else

res_x[i] = x[i] + d;

}

if (y[i] > y[first] || (y[i] == y[first] && x[i] < x[first]))

first = i;

}

}

void output(){

if (!clockwise){

for (int i = first; i <= n; i++)

cout << res_x[i] << " " << res_y[i] << endl;

for (int i = 1; i < first; i++)

cout << res_x[i] << " " << res_y[i] << endl;

}

else{

for (int i = first; i >= 1; i--)

cout << res_x[i] << " " << res_y[i] << endl;

for (int i = n; i > first; i--)

cout << res_x[i] << " " << res_y[i] << endl;

}

}

int main(){

freopen("CONTOUR.INP", "r", stdin);

freopen("CONTOUR.OUT", "w", stdout);

input();

define_direction();

process();

output();

return 0;

}

Page 62: ĐỊNH HƢỚNG CHUYÊN MÔN o b ng h ọc A ĐỊNH HƢỚNGchuyenlequydonlaichau.edu.vn/upload/32237/20190808/P_He_2011.pdf · Việc đào tạo, bồi dưỡng học sinh giỏi

62/64

MUA KEM Tên chương trình: CREAM.???

Rasmus và các bạn đi nghỉ hè ở Ý. Thời tiết quá nóng bức, các bạn quyết định mua mỗi

người vài cây kem cho đã khát. Có n loại kem mùi khác nhau đánh số từ 1 đến n. Có một số

cặp mùi kỵ nhau làm mất ngon. Rasmus muốn biết có bao nhiêu cách mua 3 cây kem không

có cặp mùi kỵ nhau. Trình tự mua không đóng vai trò quan trọng.

Ví dụ, n = 5 và số cặp mùi kỵ nhau m =3: (1, 2), (3, 4) và (1, 3). Khi đó Rasmus có 3 cách

mua: (1, 4, 5), (2, 3, 5) và (2, 4, 5).

Dữ liệu: Vào từ file văn bản CREAM.INP:

Dòng đầu tiên chứa 2 số nguyên n và m (1 ≤ n ≤ 200, 0 ≤ m ≤ 104),

Mỗi dòng trong m dòng sau chứa 2 số nguyên p và q – cặp mùi kỵ nhau, 1 ≤ p, q ≤ n, p ≠ q,

không có cặp mùi nào bị nêu lặp lại.

Kết quả: Đưa ra file văn bản CREAM.OUT một số nguyên – số cách mua.

Ví dụ:

CREAM.INP CREAM.OUT 5 3

1 2

3 4

1 3

3

C++ #include <iostream>

using namespace std;

int n, m, u, v, res = 0;

bool contrast[201][201];

int main(){

freopen("CREAM.INP", "r", stdin);

freopen("CREAM.OUT", "w", stdout);

scanf("%d %d", &n, &m);

while (m--){

scanf("%d %d", &u, &v);

contrast[u][v] = contrast[v][u] = true;

}

for (int i = 1; i <= n-2; i++)

for (int j = i+1; j <= n-1; j++)

for (int k = j+1; k <= n; k++)

res += !(contrast[i][j] || contrast[i][k] ||

contrast[j][k]);

printf("%d", res);

return 0;

}

Page 63: ĐỊNH HƢỚNG CHUYÊN MÔN o b ng h ọc A ĐỊNH HƢỚNGchuyenlequydonlaichau.edu.vn/upload/32237/20190808/P_He_2011.pdf · Việc đào tạo, bồi dưỡng học sinh giỏi

63/64

HÌNH KHỐI Tên chương trình: CUBES.???

Từ một hình lập phương ban đầu (gọi là hình khối bậc 0) người ta dán vào các mặt của nó

hình lập phương cùng kích thước và được hình khối bậc 1. Từ hình khối bậc 1 người ta dán

các hình lập phương vào các mặt trống của nó và được hình khối bậc 2 (Xem hình vẽ). Từ

hình khối bậc i người ta tạo ra hình khối bậc i+1 bằng cách dán các hình lập phương vào các

mặt trống của nó.

Yêu cầu: Cho số nguyên n ( 0 ≤ n ≤ 100 000). Hãy xác định số khối lập phương tạo ra hình

khối bậc n.

C++ #include <iostream>

#include <fstream>

using namespace std;

int n, m, u, v, res = 0;

int c[201][201];

int main()

{ ifstream fi ("CREAM.INP");

ofstream fo ("CREAM.OUT");

fi>>n>>m;

{int c[n+1][n+1],t;

memset(c,0,sizeof(c));

for (int i=1;i<=m;i++)

{fi>>u>>v;

c[u][v]=c[v][u]=1;

}

for (int i = 1; i <= n-2; i++)

for (int j = i+1; j <= n-1; j++)

for (int k = j+1; k <= n; k++)

{t=c[i][j]+c[i][k]+c[j][k];

if (t==0) res++;

}

}

fo<<res;

fo.close(); fi.close();

}

Hình khối

bậc 0

Hình khối

bậc 1

Hình khối

bậc 2

Page 64: ĐỊNH HƢỚNG CHUYÊN MÔN o b ng h ọc A ĐỊNH HƢỚNGchuyenlequydonlaichau.edu.vn/upload/32237/20190808/P_He_2011.pdf · Việc đào tạo, bồi dưỡng học sinh giỏi

64/64

Dữ liệu: Vào từ file văn bản CUBES.INP, gồm nhiều Tests, mỗi test cho bởi số nguyên n,

ghi trên một dòng.

Kết quả: Đưa ra file văn bản CUBES.OUT, kết quả mỗi test là một số nguyên, ghi trên một

dòng.

Ví dụ:

CUBES.INP CUBES.OUT

1

2

7

25

C++ #include <fstream>

using namespace std;

ifstream fi ("CUBES.INP");

ofstream fo ("CUBES.OUT");

int n,ho,hn,co,cn,r;

int main()

{while (!fi.eof())

{hn=1;cn=1;

fi>>n;

for (int i = 1; i<n;i++)

{ho=hn;co=cn;

cn=co+i*4;

hn=ho+cn;

}

r=cn+2*ho;

fo<<r<<endl;

}

fo.close(); fi.close();

}