Tải bản đầy đủ (.pdf) (21 trang)

CHUYÊN đề 2 một số THUẬT TOÁN cơ bản PYTHON THCS

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (884.97 KB, 21 trang )

TÀI LIỆU BỒI DƯỠNG HỌC SINH GIỎI TIN HỌC BẬC THCS

CHUYÊN ĐỀ 2:
MỘT SỐ THUẬT TOÁN CƠ BẢN
Tác giả: NGƯT Nguyễn Tấn Phong
Đơn vị: Trường THCS Đồng Nai, huyện Cát Tiên, tỉnh Lâm Đồng
PHẦN I. CÁC DẠNG TOÁN, THUẬT TOÁN CỦA ĐỀ THI HSG TIN THCS
1. Định hướng đề thi
- Thuật toán đa dạng, phù hợp với nhiều mức độ năng lực học sinh, bám sát theo
xu hướng ra đề chung của các huyện và tình hình học sinh. Mỗi bài tốn ln có nhiều
phương án giải khác nhau, độ phức tạp và tối ưu thuật toán khác nhau.
- Đề gồm 3 hoặc 4 bài, có thể chia đều điểm/bài theo thang 20 điểm.
2. Các dạng toán thường gặp
2.1. Dạng 1: Dạng toán số học, xử lý phạm vi dữ liệu số
Các bài toán số học cơ bản với số nguyên (hai hoặc ba số) như tìm UCLN, BCNN
của số nguyên, số nguyên tố, tính tổng quy luật, tổng liên tiếp, …. Dùng hàm số học cơ
bản //,%, abs(), sqrt(), … như tách số, xác định tính chẵn lẻ, …
Các bài toán số học đơn giản trên dãy số mà phần tử của dãy mô tả được bằng
phương pháp liệt kê hoặc chỉ ra tính chất đặc trưng và có giới hạn số phần tử, như liệt
kê số phần tử dãy số, tìm phần tử thứ i dãy số, tổng phần tử dãy số (VD: dãy số nguyên
tố, dãy số fibonacci, dãy lucas, dãy số tiến, …).
2.2. Dạng 2: Các bài toán mảng một chiều và xâu ký tự
Sử dụng các thuật toán cơ bản mảng một chiều, string như sắp xếp, tìm kiếm phần
tử thỏa tính chất, thêm bớt, …; chuỗi đối xứng, loại bỏ ký tự trùng nhau, chuyển đổi chuỗi
thành số, …
Các thuật toán về dãy số đơn điệu mà phần tử của dãy không mô tả được bằng
phương pháp liệt kê hoặc chỉ ra tính chất đặc trưng như phần tử tăng liên tiếp, giảm
liên tiếp, dãy con thỏa tính chất, dãy con bị chặn, …
2.3. Dạng 3: Các bài toán mảng hai chiều, gắn liền thực tiễn
Sử dụng các thuật toán cơ bản trên mảng hai chiều (ma trận số) như sắp xếp, tìm
kiếm, … theo hàng, theo cột, theo đường chéo.


Bài toán với thuật tốn có độ phức tạp cao, có thể giải bằng nhiều thuật tốn. Đề
bài là những bài tốn mang tính thực tế có liên hệ với cuộc sống (định hướng hướng phát
triển năng lực học sinh, theo hướng tích hợp), sử dụng thuật tốn nâng cao để phân hóa
và xét chọn giải cho học sinh.
3. Biểu điểm và định hướng chấm
- Chấm tự động bằng phần mềm Themis và chấm code để phân hóa.
- Dịch thành cơng chương trình và đọc được dữ liệu từ file lên biến nhớ 1đ/1bài
(chấm tự động và chấm code).
- Mỗi bài chấm từ 4 -> 5test (gồm 2 test dữ liệu nhỏ, 2 test dữ liệu lớn, 1 test biên
hoặc cực biên), mỗi test 1 điểm (chấm tự động).
- Giới hạn thời gian tối đa 5s.
- Xét giải ưu tiên điểm trước, sau đó đến thuật toán.


2
PHẦN II. CÁC DẠNG TOÁN, THUẬT TOÁN CƠ BẢN
I. Quy ước lại khái niệm thuật giải và thuật toán
Thuật giải: Là tập hợp các bước tuần tự để giải hoàn chỉnh một bài tốn, một số
bước trong thuật giải có thể thay đổi vị trí mà khơng ảnh hưởng đến kết quả.
Thuật toán: Là tập hợp các bước tuần tự gồm phép toán và câu lệnh để giải bài
toán, các bước và phép tốn trong thuật tốn khơng thể thay đổi được.
Ví dụ 1:

Ví dụ 2: Viết chương trình tìm số lớn nhất (max) trong hai số.
Thứ tự các bước phải làm là:

II. Xây dựng hàm để giải các bài toán thực tế
Đặt vấn đề: Hàm trong giải toán tin học rất quan trọng, nó có tính then chốt để có
thể giải hồn chỉnh một bài tốn. Tất cả các ngơn ngữ lập trình đều có phần định nghĩa
hàm (function/define).

Thơng thường hàm có hai kiểu trả về giá trị là trả về giá trị là số hoặc trả về giá
trị logic dạng True/False. Nếu cần tính tốn kết quả nào đó thì xây dựng hàm trả về giá
trị số, nếu để kiểm tra tính chất thì trả về giá trị logic True/False.
Đối với python, hàm có thể trả về cùng lúc nhiều giá trị hoặc một dữ liệu có cấu
trúc như chuỗi hay danh sách, ..
Các ví dụ xây dựng hàm:
Ví dụ 1: Viết hàm tính tổng các chữ số của một số nguyên dương n
---> với kiểu trả về là số
def tongcs(n):
stam = 0
for i in str(n): stam = stam + int(i)
return stam

<>cách khác<>

def tongcs(n):
return sum(map(int,str(n)))

Ví dụ 2: Viết hàm kiểm tra tổng các chữ số của một số nguyên dương n là số chẵn
hay lẻ ---> kiểu tra về là logic True/False


3
def kttongcs(n):
stam = 0
for i in str(n): stam = stam + int(i)
if stam%2==0: return True
else: return False

Ví dụ 3: Viết hàm kiểm tra số nguyên tố n ---> kiểu tra về là logic True/False

def ktnt(n):
if n<2: return False
for i in range(2,n//2+1):
if n%i==0: return False
return True

Ví dụ 4: Bài 1 đề Đức Trọng (2020 – 2021)

---> kết hợp các hàm với nhau

def tongcs(n):
stam = 0
for i in str(n): stam = stam + int(i)
return stam
def ktnt(n):
if n<2: return False
for i in range(2,n//2+1):
if n%i==0: return False
return True
#Chương trình chính
if ktnt(tongcs(n)): print(‘YES’)
else: print(‘NO’)

III. List Comprehensions
Cú pháp tạo:
[<action> for <item> in <iterrator> if <some condition>]
Trong đó:
- List Comprehensions là một danh sách cần tạo mới, ta gọi là newlist
- <action> là một hành động/thao tác cần thực hiện với phần tử newlist
- <item> đối tượng (ảo) chỉ có tác động trong cú pháp newlist

- <iterrator> là đối tượng tuần tự/có thể lặp được, gồm: str, list, tuple, range, list
comprehension.
- <some condition> biểu thức điều kiện
Các ví dụ:
Ví dụ 1: Tách các chữ số của một số nguyên N đưa vào một danh sách.
N = 5632475
[x for x in str(N)]
--> khi dòng lệnh được thực thi thì sẽ có một list mới được tạo ra chứa các số:
['5', '6', '3', '2', '4', '7', '5']


4
nhưng nó khơng được gán cho một danh sách cụ thể nào hết. Muốn truy xuất hãy dùng
một biến để lưu lại.
N = 5632475
a=[x for x in str(N)]
print(a)
Ví dụ 2: Lấy các chữ số lẻ của N/lập phương các chữ số của N
[x for x in str(N) if int(x)%2!=0]
[int(x)**3 for x in str(N)]
Ví dụ 3: Tìm số ngun tố trong dãy A
A = [7,5,11, 18, 25, 27, 29, 15]
def ktnt(a):
if a<2: return False
for i in range(2,a//2+1):
if a%i==0: return False
return True
print([x for x in A if ktnt(x)])
Ví dụ 4: Loại bỏ các chữ giống nhau trong 1 chuỗi hay các số giống nhau trong
mảng 1 chiều (tỉa chuỗi, mảng)

#tỉa chuỗi/tỉa mảng bằng List Comprehension
a = [7,5,11, 5, 25, 7, 29, 25]
s='aabccddefefabcd12511237'
b=[]
[b.append(x) for x in a if x not in b]
c=[]
[c.append(x) for x in s if x not in c]
print(b)
print(c)
Ví dụ 5: Tìm số tự mãn trong dãy
Qui ước: Số tự mãn bậc 3 là những số bằng tổng lập phương các chữ số của nó.
Ví dụ: Số 153 là số tự mãn vì 153 = 13 + 53 + 33.
Cho dãy gồm N phần tử là số nguyên dương A1, A2, ... , An; (00Dữ liệu vào từ file: SOTUMAN.INP
- Dòng đầu tiên chứa số nguyên dương N.
- Dòng thứ hai chứa N số nguyên dương, các số cách nhau một khoảng trắng.
Kết quả ra file: SOTUMAN.OUT
- Dòng đầu tiên ghi các số tự mãn tìm được theo thứ tự tăng dần, các số cách
nhau một khoảng trắng.
Ví dụ:
SOTUMAN.INP SOTUMAN.OUT
5
153 371
6 371 18 153 28


5
Dùng list comprehension


A = [6, 371, 18, 153, 28]
#cách 1: tường minh
b = []
for i in A:
if i==sum([int(x)**3 for x in str(i)]): b.append(i)
#cách 2: gọn lẹ
c=[]
c.append(x) for x in A if x ==sum([int(y)**3 for y in str(x)])]
print(sorted(b))
print(sorted(c))

IV. Lớp cắt/đoạn con của <iterrator>
a. Cú pháp tạo:
<iterrator>[index start:index end:step]
Trong đó:
Tạo một <iterrator> mới có số phần tử từ index start đến index end -1 và
bước nhảy bỏ qua phần tử step
- <iterrator> là đối tượng tuần tự/có thể lặp được, gồm: str, list, tuple, range,
list comprehension
- index start: chỉ số đầu, không có mặc định là 0
- index end: chỉ số cuối, khơng có mặc định là chiều dài của <iterrator> + 1
- step: bước nhảy, khoảng cách bỏ qua chỉ số, mặc định là 1
b. Ví dụ: Cho dãy A = [6, 371, 18, 153, 28, 15]
Các truy xuất sau được gọi là lớp cắt của list A
A[2:5] -> [18, 153, 28]
A[2:] -> [18,153,28,15]
A[:3] -> [6,371,18]
A[:3:2] -> [6,18]
A[2::2] -> [18:28]
Các ví dụ ứng dụng lớp cắt để giải các bài toán của <iterrator> có tính liên tiếp.

Ví dụ 1: Tính tổng một đoạn con
A = [6, 371, 18, 153, 28, 15]
sum(A[:4])
Ví dụ 2: Kiểm tra đoạn con có các phần tử dương
A = [6,-371,-18,153,28,15]
def dayconduong(a):
for i in a:
if i<0: return False
return True
#tìm các dãy con dương trong A
n = len(A)
for i in range(n):
for j in range(i+1,n+1):
if dayconduong(A[i:j]): print(A[i:j])
---> Kết quả sẽ cho ra nhiều dãy con thỏa điều kiện dương, nếu ta gán tất cả các
kết quả này vào một mảng 2 chiều thì ta gọi đó là bảng phương án khả thi.


6
A = [6, -371, -18, 153, 28, 15]
def dayconduong(a):
for i in a:
if i<0: return False
return True
#tìm các dãy con dương trong A
n = len(A)
c=[]
for i in range(n):
for j in range(i+1,n+1):
if dayconduong(A[i:j]): c.append(A[i:j])

print(c)
mảng c ở đây là mảng 2 chiều và gọi là bảng các phương án khả thi.
Ví dụ 3: Tìm tất cả các đoạn con dương có số phần tử lớn nhất
A = [6, -371, -18, 153, 28, 15]
#hàm trả về kết quả dãy dương True/False

def dayconduong(a):
for i in a:
if i<0: return False
return True
#liệt kê một bảng phương án khả thi và điều kiện tìm kiếm khả thi

n = len(A)
c=[]
lenmax=0
for i in range(n):
for j in range(i+1,n+1):
if dayconduong(A[i:j]):
c.append(A[i:j])
if lenmax#xuất các phương án thỏa điều kiện từ bảng phương án khả thi

for i in c:
if len(i)==lenmax: print(i)
Ví dụ 4: Xuất chỉ số bắt đầu và số phần tử của của dãy con dương dài nhất
for i in c:
if len(i)==lenmax:
print(A.index(i[0]),' ',len(i))
#index là một hàm tìm kiếm chỉ số trên <iterrator>



7
I. DẠNG 1 - CÁC BÀI TOÁN SỐ HỌC CƠ BẢN
Bài 1. Tính tổng liên tiếp
Viết chương trình tính tổng các số nguyên dương liên tiếp không quá N (n <106).
Dữ liệu vào từ file: BAI1.INP
- Dòng đầu tiên ghi số nguyên dương N (n < 106).
Kết quả ra file: BAI1.OUT
- Dịng đầu tiên ghi tổng các số ngun tính được.
Ví dụ:
BAI1.INP
BAI1.OUT
3
6
5
15
⸙Thuật tốn:
Tính S = 1 + 2 + 3 + … + N
ↈCode tham khảo:
1 #Đọc dữ liệu INP
2 fi = open('bai1.inp')
3 n = int(fi.read())
4 fi.close()
5 #Thuật toán
6 tong = 0
7 for i in range(n+1):
tong = tong + i
8
9 #Ghi vào file OUT
10 fo = open('bai1.out','w')

11 print(tong,file=fo)
12 fo.close()
Cách viết khác mở file bằng câu lệnh with
1 #Đọc dữ liệu INP
2 with open('bai1.inp')as fi:
n = int(fi.read())
3
4 #Thuật toán
5 tong = 0
6 for i in range(n+1):
tong = tong + i
7
8 #Ghi vào file OUT
9 with open('bai1.out','w')as fo:
print(tong,file=fo)
10
☼Tìm hiểu thêm:
*/ Sự khác biệt giữa mở file bằng hàm open và bằng câu lệnh with
Chúng ta đều có thể sử dụng hàm open lẫn câu lệnh with để mở file trong python.
Việc lựa chọn phương pháp nào thì tuỳ theo sở thích của mỗi lập trình viên, tuy nhiên thì
hai phương pháp này cũng có điểm khác biệt, đó chính là trong cách đóng lại file sau khi


8
mở. Với file được mở bằng hàm open, chúng ta phải đóng lại file đó sau khi đã mở và
thao tác xong với file. Tuy nhiên thì đối với file được mở bằng câu lệnh with, chúng ta
không cần phải đóng lại file sau khi mở, vì câu lệnh with vốn tự động đóng lại file cho
chúng ta rồi.
*/ Ghi dữ liệu vào file bằng phương thức <biến file>.write()
Tại dòng 10 ta có thể thay câu lệnh print(tong,file=fo)bằng lệnh

fo.write(str(tong)).
print(giá trị cần ghi, file=<biến file>) là một hàm; điểm khác là khi ghi dữ liệu
bằng phương thức .write() thì giá trị đó phải được chuyển thành dạng chuỗi bằng hàm
str().
*/ Thuật tốn tính tổng như trên có tên gọi là cộng dồn giá trị. Khi tính tổng cần
thiết phải có một biến để lưu giữ kết quả tính sau mỗi lần lặp, biến đó phải được khởi tạo
bằng 0 trước khi tham gia vào vòng lặp cộng dồn.
tong = 0
for i in range(n+1):
tong = tong + i
Nếu khơng có câu lệnh tong = 0 kết quả vẫn đúng, không sai nhưng có thể sai
ở những trường hợp bài tốn khác.
⸎Luyện tập thêm
1
1
1
Bài 1a: Viết chương trình tính tổng 𝑆 = 1/1 + + +. . . + ?
2

3

𝑛

BAI1a.INP BAI1a.OUT
5
2.283
ↈCode tham khảo:
1 #đọc file INP
2 with open('bai1a.inp') as fi:
n=int(fi.readline())

3
4 #thuật toán
5 tong=0
6 for i in range(1,n+1):
tong = tong+1/i
7
8 #ghi file OUT
9 with open('bai1a.out','w') as fo:
print(round(tong,3),file=fo)
10
𝟏
𝟏
𝟏
Bài 1b: Viết chương trình tính tổng 𝑺 = 𝟏 + 𝟐 + 𝟐 +. . . + 𝟐 ?
𝟐
𝟑
𝒏
BAI1b.INP BAI1b.OUT
5
Bài 2. Tính tổng thỏa điều kiện chia hết
Viết chương trình tính tổng các số ngun dương chẵn liên tiếp không quá N (n <
6
10 ).


9
Dữ liệu vào từ file: BAI2.INP
- Dòng đầu tiên ghi số nguyên dương N (n < 106).
Kết quả ra file: BAI2.OUT
- Dịng đầu tiên ghi tổng các số ngun tính được.

Ví dụ:
BAI2.INP
BAI2.OUT
3
2
5
6
⸙Thuật tốn:
Lý thuyết: a/ Tính chia hết
n chia hết cho m nếu n%m == 0,
ngược lại, n không chia hết cho m nếu n%m != 0.
b/ Số chẵn là số chia cho 2 có số dư bằng 0; số lẻ là số chia
cho 2 có số dư khác 0.
ↈCode tham khảo:
1 #Đọc dữ liệu INP
2 with open('bai2.inp')as fi:
n = int(fi.read())
3
4 #Thuật toán
5 tong = 0
6 for i in range(n+1):
if i%2==0: tong = tong + i
7
8 #Ghi vào file OUT
9 with open('bai2.out','w')as fo:
print(tong,file=fo)
10
Bài 3. Tính tổng thỏa nhiều điều kiện chia hết
Viết chương trình tính tổng các số ngun dương không quá N (n < 106).
Dữ liệu vào từ file: BAI3.INP

- Dòng đầu tiên ghi số nguyên dương N (n < 106).
Kết quả ra file: BAI3.OUT
- Dòng đầu tiên ghi tổng các số chia hết cho 3 và chia hết cho 7.
- Dòng thứ hai ghi tổng các số vừa chia hết cho 4 và không chia hết cho 5.
- Dòng thứ ba ghi tổng các số chia hết cho 13 hoặc chia hết cho 15.
Ví dụ:
BAI3.INP
BAI3.OUT
Giải thích
42
63
21 + 42
160
4+8+12+16+24+28+32+36
123
13+15+26+30+39
⸙Thuật tốn:
Ứng dụng tính chất chia hết bằng phép tốn % kết hợp với hàm or, and.
ↈCode tham khảo:
1 #Đọc dữ liệu INP
2 with open('bai3.inp') as fi:
n = int(fi.read())
3


10
#Thuật toán
tong1 = 0
for i in range(n+1):
if i%3==0 and i%7==0: tong1 = tong1 + i

tong2 = 0
for i in range(n+1):
if i%4==0 and i%5!=0: tong2 = tong2 + i
tong3 = 0
for i in range(n+1):
if i%13==0 or i%15==0: tong3 = tong3 + i
#Ghi vào file OUT
with open('bai3.out','w')as fo:
print(tong1,tong2,tong3,sep='\n',file=fo)
print(tong1,file=fo)
print(tong2,file=fo)
print(tong3,file=fo)
☼Tìm hiểu thêm:
- Câu lệnh: print(tong1,tong2,tong3,sep='\n',file=fo)
Tương ứng với 3 câu lệnh:
print(tong1,file=fo)
print(tong2,file=fo)
print(tong3,file=fo)
- Trong hàm print() có hai chỉ thị thường dùng để ghi dữ liệu là vào file là:
sep='kí tự' ---> giữa các giá trị cần ghi là 'kí tự'
end='kí tự' ---> kết thúc lệnh cần ghi là 'kí tự'
với '\n' là xuống dịng.
Bài 4. Ứng dụng tính chất chia hết để tìm ước của một số dương
Viết chương trình tìm các ước của số nguyên dương N (n < 106).
Dữ liệu vào từ file: BAI4.INP
- Dòng đầu tiên ghi số nguyên dương N (n < 106).
Kết quả ra file: BAI4.OUT
- Dòng đầu tiên ghi các ước của số nguyên N, mỗi số cách nhau một khoảng trắng.
- Dòng thứ hai, ghi tổng các ước của N (kể cả N).
- Dòng thứ ba, nếu N là số hồn hảo thì ghi CO, ngược lại ghi KHONG.

Ví dụ:
BAI4.INP
BAI4.OUT
10
1 2 5 10
18
KHONG
28
1 2 4 7 14 28
56
CO
⸙Thuật toán:
Lý thuyết số:
4
5
6
7
8
9
10
11
12
13
14
15
16


11
- Ước của một số dương N, là các số i <=N mà N%i== 0.

- Cho a và b là hai số đếm được, nếu a chia hết cho b thì b được gọi là ước số của
a. Chẳng hạn số 12 có các ước số là 1, 2, 3, 4, 6 và 12. Trong các ước của a thì loại trừ a
là ước số lớn nhất của a, ta gọi các ước số khác nhỏ hơn là ước số thực sự của a.
- Nếu tổng các ước số thực sự của a cũng bằng a thì ta gọi a là số hồn hảo.
Chẳng hạn số 6 có các ước số thực sự là 1, 2 và 3. Ta có: 1 + 2 + 3 = 6 thì 6 là số hồn
hảo. Một thí dụ khác về số hồn hảo là số 28. Số này có các ước số thực sự là 1, 2, 4, 7,
14 với 1 + 2 + 4 + 7 + 14 = 28.
ↈCode tham khảo (viết theo từng ý, chưa tối ưu):
1 #đọc file INP
2 with open('bai4.inp') as fi:
n=int(fi.read())
3
4 #ghi file OUT
5 with open('bai4.out','w') as fo:
#ý 1
6
for i in range(1,n+1):
7
if n%i==0:
8
print(i,end=' ',file=fo)
9
#ý 2
10
print(file=fo)
11
tong=0
12
for i in range(1,n+1):
13

if n%i==0:tong=tong+i
14
print(tong,file=fo)
15
#ý 3
16
tongts=0
17
for i in range(1,n//2+1):
18
if n%i==0:tongts=tongts+i
19
if tongts==n:print('CO',file=fo)
20
else:print('KHONG',file=fo)
21
ↈCode tham khảo (tối ưu dòng lệnh):
1 #Đọc dữ liệu INP
2 with open('bai4.inp') as fi:
n = int(fi.read())
3
4 #Thuật toán và Ghi vào file OUT
5 with open('bai4.out','w')as fo:
tonguoc=0
6
for i in range(1,n+1):
7
if n%i==0:
8
print(i,end=' ',file=fo)

9
tonguoc = tonguoc+i #tính tổng các ước
10
print(file=fo) # để xuống dịng
11
print(tonguoc,file=fo)
12


12
if tonguoc == 2*n: print('CO',file=fo)
13
else: print('KHONG',file=fo)
14
☼Tìm hiểu thêm: - Cách viết thuật toán và ghi file OUT như trên gọi là cách ghi file trực
tiếp ngay trong thuật toán.
Bài 5: Vận dụng tính chia hết để tìm ước chung của hai hay nhiều số
Viết chương trình tìm các ước chung của ba số nguyên dương a,b,c (a,b,c < 106).
Dữ liệu vào từ file: BAI5.INP
- Dòng đầu tiên ghi ba số nguyên dương a, b và c cách nhau một khoảng trắng.
Kết quả ra file: BAI5.OUT
- Dòng đầu tiên ghi các ước chung của ba số, các số cách nhau một khoảng trắng.
Ví dụ:
BAI5.INP
BAI5.OUT
24 8 32
1248
7 25 5
1
⸙Thuật tốn:

Lý thuyết số:
- Ước chung của hai số a, b là số k nếu (a%k==0) and (b%k ==0).
- Số 1 là ước chung của tất cả các số.
- Thuật tốn tìm ước chung của 3 số a, b, c:
+ Duyệt từ k chạy từ 1 đến a, nếu (a%k == 0) and (b%k == 0) and (c%k == 0) thì
k là ước chung của a, b, c. Tương tự cách tìm cho nhiều số.
Cài đặt code theo thuật toán trên:
for k in range(1,a+1):
if (a%k==0)and(b%k==0)and(c%k==0):print(k)
*Vấn đề tối ưu:
- Thuật tốn trên là khơng tối ưu nhưng chắc chắn luôn đúng.
- Để tối ưu ta tìm min(a,b,c), rồi duyệt k chạy từ 1 đến min(a,b,c)
for i in range(1,min(a,b,c)+1):
if (a%k==0)and(b%k==0)and(c%k==0):print(i)
ↈCode tham khảo:
1 #Đọc dữ liệu INP
2 with open('bai5.inp') as fi:
a,b,c = map(int,fi.readline().split())
3
4 #Thuật toán và Ghi vào file OUT
5 with open('bai5.out','w')as fo:
for k in range(1,min(a,b,c)+1):
6
if(a%k==0)and(b%k==0)and(c%k==0):print(k,end=' ',file=fo)
7
☼Tìm hiểu thêm: - Trong python có sẵn hàm min(), max() của hai hay nhiều số.
Bài 6: Vận dụng tính chia hết để tìm UCLN và BCNN của 2 hay nhiều số
Viết chương trình tìm các UCLN và BCNN của ba số nguyên dương a,b,c
(a,b,c<106).
Dữ liệu vào từ file: BAI6.INP

- Dòng đầu tiên ghi ba số nguyên dương a, b và c cách nhau một khoảng trắng.
Kết quả ra file: BAI6.OUT


13
- Dòng đầu tiên ghi UCLN của ba số.
- Dòng thứ hai ghi BCNN của ba số.
- Dòng thứ ba ghi lần lượt các BC khơng q 102
Ví dụ:
BAI6.INP
BAI6.OUT
8 16 32
8
32
32 64 96
⸙Thuật toán:
Lý thuyết số:
- UCLN(a,b,c) là số lớn nhất trong các UC(a, b, c)
- BCNN(a,b) = (a*b)/UCLN(a,b)
ↈCode tham khảo:
1 #đọc file INP
2 with open('bai6.inp') as fi:
a,b,c=map(int,fi.readline().split())
3
4 import math
5 ucln=math.gcd(a,b,c)
6 bcnn1=a*b//math.gcd(a,b)
7 bcnn2=c*bcnn1//math.gcd(bcnn1,c)
8 #ghi file OUT
9 with open('bai6.out','w') as fo:

print(ucln,file=fo)
10
print(bcnn2,file=fo)
11
for i in range(1,100):
12
if bcnn2*i<10**2:print(bcnn2*i,end=' ',file=fo)
13
☼Tìm hiểu thêm:
- Trong python có sẵn thư viện gồm các hàm toán học cơ bản. Muốn sử dụng thư
viện này thì cần viết lệnh: import math
- Các hàm số học thường dùng:
Tên
Công dụng
math.pi
Số  (3.141592…)
math.sqrt(x)
Căn bậc 2 của x
math.floor(x)
Làm tròn xuống
math.ceil(x)
Làm tròn lên
math.trunc(x)
Bỏ phần thập phân của số thực x
math.factorial(n) n! = 1.2..n
math.gcd(a,b)
Ước chung lớn nhất của a và b
math.sin(x)
Các hàm lượng giác
math.cos(x)

math.tan(x)
math.asin(x)
math.acos(x)


14
math.atan(x)
Bài 7: Xác định tính nguyên tố của một số bằng phướng pháp tìm ước
Viết chương trình tìm các ước của số nguyên dương N (n < 106).
Dữ liệu vào từ file: BAI7.INP
- Dòng đầu tiên ghi số nguyên dương N (n < 106).
Kết quả ra file: BAI7.OUT
- Nếu số N là nguyên tố thì ghi CO, ngược lại ghi KHONG.
Ví dụ:
BAI7.INP
BAI7.OUT
7
CO
⸙Thuật tốn:
Lý thuyết số:
- Số ngun tố là số chỉ có hai ước là 1 và chính nó.
- Thuật toán: Nếu tồn tại một số 1là số nguyên tố.
- Thuật toán dựa trên kĩ thuật “Đặt cờ hiệu”:
Bước 1: Giả sử số N là số nguyên tố.
Bước 2: Tìm kiếm từ 2 đến (N//2+1) để phủ nhận bước 1.
Bước 3: Trả lời kết luận.
ↈCode tham khảo:
1 #Đọc dữ liệu INP
2 with open('bai7.inp') as fi:

n = int(fi.read())
3
#Thuật
toán
4
5 ktnt='CO'
6 for i in range(2,n//2+1):
if n%i==0:
7
ktnt='KHONG'
8
break
9
10 #Ghi vào file OUT
11 with open('bai7.out','w')as fo:
print(ktnt,file=fo)
12
☼Tìm hiểu thêm:
Bài 8: Tách các chữ số của một số ngun
Viết chương trình tính tổng các chữ số của một số nguyên dương N (n < 106).
Dữ liệu vào từ file: BAI8.INP
- Dòng đầu tiên ghi số nguyên dương N (n < 106).
Kết quả ra file: BAI8.OUT
- Dòng đầu tiên ghi tổng tìm được.
Ví dụ:
BAI8.INP
BAI8.OUT
16
7
⸙Thuật tốn:



15
Lý thuyết số: Nếu số nguyên N có a chữ số, thì ta thực hiện liên tiếp (a-1) lần phép tính
(n=n//10) và từng chữ số từ phải qua trái sẽ là phép (n%10) thì sẽ tách được hết các chữ
số.
ↈCode tham khảo:
1 #Đọc dữ liệu INP
2 with open('bai8.inp') as fi:
n = int(fi.read())
3
4 #Thuật toán
5 tongcs=0
6 for i in range(1,len(str(n))+1):
tongcs = tongcs + (n%10)
7
n=n//10
8
9 #Ghi vào file OUT
10 with open('bai8.out','w')as fo:
print(tongcs,file=fo)
11
☼Tìm hiểu thêm: - Trên đây là thuật toán thường gặp. Ngồi ra, trong python có một số
cách khác tính tổng các chữ số của một số nguyên vô cùng đơn giản như sau:
tongcs = sum(map(int,str(n))) Tính tổng các chữ số của N
list(str(n))
Liệt kê các chữ số của N
⸎Luyện tập thêm: Một số ứng dụng kĩ thuật tách chữ số
Đôi khi trong thực tế cuộc sống, con người thường tự quy ước một số tính chất nào
đó của một số số học. Chẳng hạn: số điện thoại cầu tài, số tứ quý, số ngũ linh, số thần tài,

số tiến, nút của một số, số đẹp, …. Những quy ước này mang tính tự phát khơng hẳn là
tính chất số học theo lý thuyết số. Các ví dụ dưới đây là một cách quy ước như vậy:
Bài 9a: Kiểm tra số đẹp
Quy ước:
- Số đẹp là số mà có tổng các chữ số chia cho 10 có số dư là 9 (nút).
- Số tiến là số có hai chữ số trở lên và các chữ số theo thứ tự từ trái qua phải là tăng
dần.
Viết chương trình kiểm tra một số nguyên dương N có là số theo quy ước như trên
khơng?
Dữ liệu vào từ file: SODEP.INP
- Dòng đầu tiên ghi số nguyên dương N (n < 106).
Kết quả ra file: SODEP.OUT
- Dòng đầu tiên, nếu số N là số số đẹp thì ghi CO, ngược lại ghi KHONG.
- Dịng thứ hai, nếu N là số tiến thì ghi số -1, ngược lại thì ghi số 0.
Ví dụ:
SODEP.INP SODEP.OUT
2359
CO
-1
7
KHONG
0
⸙Thuật tốn:


16
Lý thuyết số: Nếu số nguyên N có a chữ số, thì ta thực hiện liên tiếp (a-1) lần phép
tính (n=n//10) và từng chữ số từ phải qua trái sẽ là phép (n%10) thì sẽ tách được hết các
chữ số.
ↈCode tham khảo:

1 #Đọc dữ liệu INP
2 with open('sodep.inp') as fi:
n = int(fi.read())
3
4 #Thuật toán
5 sodep='CO'
6 if sum(map(int,str(n)))%10!=9: sodep='KHONG'
7 #b
8 if len(str(n))>=2:sotien=-1
9 else:sotien=0
10 for i in range(1,len(str(n))+1):
for j in range(i+1,len(str(n))+1):
11
if i>=j:
12
sotien=0
13
break
14
15 #Ghi vào file OUT
16 with open('sodep.out','w')as fo:
print(sodep,file=fo)
17
print(sotien,file=fo)
18
☼Tìm hiểu thêm: Có thể thay dòng lệnh từ 10 đến 14 bằng đoạn code sau:
if len(str(n))>=2:sotien=-1
else:sotien=0
while n!=0:
if (n%10)<((n//10)%10):

sotien=0
break
n=n//10
Bài 9b: Kiểm tra số giả nguyên tố
Quy ước: Số giả nguyên tố là một số nguyên tố dương và các chữ số của nó cũng
là số nguyên tố.
Viết chương trình kiểm tra một số nguyên dương N có là số giả nguyên tố theo
quy ước như trên khơng?
Dữ liệu vào từ file: GIANGTO.INP
- Dịng đầu tiên ghi số nguyên dương N (n < 106).
Kết quả ra file: GIANGTO.OUT
- Nếu số N là số giả nguyên to thì ghi CO, ngược lại ghi KHONG.
Ví dụ:
GIANGTO.INP GIANGTO.OUT
Giải thích
23
CO
3275
KHONG
Số 3275 khơng phải là số ngun tố
17
KHONG
Số 1 khơng phải là số nguyên tố


17
-37
⸙Thuật toán:

KHONG


Số -37<0

ↈCode tham khảo:
1 #Đọc dữ liệu INP
2 with open('giangto.inp') as fi:
n = int(fi.read())
3
4 #Thuật toán
5 ktgnt = 'CO'
6 if n<2: ktgnt='KHONG'
7 else:
#kiểm tra tính nguyên tố của số n
8
for i in range(2,n//2+1):
9
if n%i==0:
10
ktgnt='KHONG'
11
break
12
#kiểm tra tính nguyên tố từng chữ số của n
13
for i in list(str(n)):
14
for j in range(2,int(i)//2+1):
15
if int(i)%j==0:
16

ktgnt='KHONG'
17
break
18
19 #Ghi vào file OUT
20 with open('giangto.out','w')as fo:
print(ktgnt,file=fo)
21
☼Tìm hiểu thêm:
Bài 9c: Ứng dụng kĩ thuật tách chữ số để kiểm tra số đối xứng
Quy ước: Số nguyên n gọi là số đối xứng nếu đọc từ trái qua phải, hay từ phải qua
trái đều được số giống nhau. Ví dụ: 11,121,101 là các số đối xứng.
Viết chương trình kiểm tra một số nguyên dương N có là số đối xứng hay không
theo quy ước như trên không?
Dữ liệu vào từ file: DOIXUNG.INP
- Dòng đầu tiên ghi số nguyên dương N (n < 106).
Kết quả ra file: DOIXUNG.OUT
- Nếu số N là số đối xứng thì ghi CO, ngược lại ghi KHONG.
Ví dụ:
DOIXUNG.INP DOIXUNG.OUT
Giả thích
3
CO
71717
CO
3275
KHONG
Số 3275 đọc từ phải qua trái là 5723
⸙Thuật toán:
ↈCode tham khảo:



18
1 #Đọc dữ liệu INP
2 with open('doixung.inp') as fi:
n = int(fi.read())
3
4 #Thuật toán
5 temp=n#lưu giữ lại giá trị của n để so sánh
6 dx=0 #biến dx để lấy giá trị đảo ngược của n
7 while temp!=0:
dx=dx*10+(temp%10)
8
temp = temp//10
9
10 #Ghi vào file OUT
11 with open('doixung.out','w')as fo:
if dx==n: print('CO',file=fo)
12
else:print('KHONG',file=fo)
13
☼Tìm hiểu thêm: - Trên đây là thuật tốn thường gặp. Ngồi ra, trong python có sẵn một
hàm reversed() đảo ngược chuỗi, kết hợp với hàm list() và str() để kiểm tra bài trên đơn
giản như sau:
list(str(n))==list(reversed(str(n)))
ↈCode tham khảo:
1 #Đọc dữ liệu INP
2 with open('doixung.inp')as fi:
n = int(fi.read())
3

4 #Ghi vào file OUT
5 with open('doixung.out','w')as fo:
if list(str(n))==list(reversed(str(n))):
6
print('CO',file=fo)
7
else:
8
print('KHONG',file=fo)
9
II. DẠNG 2 - CÁC BÀI TOÁN MẢNG MỘT CHIỀU VÀ XÂU KÝ TỰ
Bài 2.1: Viết chương trình đọc từ file INP một dãy số nguyên A gồm có N phần tử
(N<=10000).
Dữ liệu vào từ file: BAI21.INP
- Dòng đầu tiên ghi số nguyên dương N (n < 106).
- Dòng tiếp theo ghi N số nguyên dương, các số cách nhau một khoảng trắng.
Kết quả ra file: BAI21.OUT
- Dòng đầu tiên, ghi dãy đã sắp xếp tăng dần.
- Dòng thứ 2 ghi tổng các phần tử của dãy.
- Dòng thứ 3 đếm các số dương trong dãy.
- Dòng 4 ghi các số nguyên tố có trong dãy, theo thứ tự tăng dần, các số cách nhau
một khoảng trắng.
Ví dụ:
BAI21.INP
BAI21.OUT
6
-9 -5 4 6 7 11
11 -5 6 7 -9 4
14



19
4
7 11
⸙Thuật toán:
ↈCode tham khảo:
1 with open('bai21.inp') as fi:
n = int(fi.readline())
2
a=list(map(int,fi.readline().split()))
3
4 #hàm kiểm tra số nguyên tố
5 def ktnt(n):
if n<2: return False
6
for i in range(2,n//2+1):
7
if n%i==0: return False
8
return True
9
10 #Thuật toán và ghi file OUT
11 with open('bai21.out','w') as fo:
a.sort() #sắp xếp tăng dần
12
for i in a:
13
print(i, end=' ',file=fo)
14
print(file=fo)

15
#tổng các phần tử dãy
16
print(sum(a),file=fo)
17
#đếm số dương trong dãy
18
dem = 0
19
for i in a:
20
if i>0: dem = dem+1
21
print(dem,file=fo)
22
#ghi các số nguyên tố trong dãy
23
for i in a:
24
if ktnt(i): print(i, end=' ',file=fo)
25
☼Tìm hiểu thêm: - Trong python có hàm .sort() để sắp xếp một dãy hoặc một chuỗi. Cú
pháp như sau:
<biến list>.sort()
Sắp xếp dãy tăng dần
<biến list>.sort(reverse=True) Sắp xếp dãy giảm dần
Ngoài ra, ta có thể dùng phương thức sorted() để tạo ra một dãy mới đã được sắp
xếp nhưng không làm thay đổi thứ tự phần tử trong danh sách ban đầu.
<list mới> =sorted(<biến list cũ>)
<list mới> =sorted(<list cũ>,reverse=True)


Sắp xếp tăng dần list cũ rồi gán cho list mới.
Sắp xếp giảm dần list cũ rồi gán vào list mới.

Bài 2.2: Viết chương trình đọc từ file INP một dãy số nguyên A gồm có N phần tử
(N<=10000). Ghi vào file OUT dãy đã loại bỏ các phần tử trùng lặp, mỗi phần tử chỉ giữ
lại một phần tử đại diện và thứ tự các phần tử không thay đổi (tỉa mảng).
BAI22.INP
10

BAI22.OUT
7 5 12 9 8 3


20
7 5 12 5 9 8 3 9 7 5
⸙Thuật toán:
ↈCode tham khảo:
1 #đọc dữ liệu từ file INP
2 with open('bai22.inp') as fi:
n = int(fi.readline())
3
a=list(map(int,fi.readline().split()))
4
5 #Thuật toán và ghi file OUT
6 with open('bai22.out','w') as fo:
b=[]
7
for i in a:
8

if b.count(i)==0: b.append(i)
9
for i in b: print(i,end=' ',file=fo)
10
☼Tìm hiểu thêm:
- Thuật tốn trên sử dụng một list b để lưu giữ kết quả tìm được, cách làm như vậy
vậy gọi là “Kĩ thuật mảng phụ”.
Ngồi ra trong python, có thể dùng List Comprehensions giải bài toán này như
sau:
b=[]
[b.append(x) for x in a if x not in b]
Bài 2.3: Cho dãy gồm N phần tử là số nguyên dương a1, a2, ... , an; (00một số nguyên dương?
Dữ liệu vào từ file: BAI23.INP
- Dòng đầu tiên chứa số nguyên dương N.
- Dòng thứ hai chứa N số nguyên dương, các số cách nhau một khoảng trắng.
Kết quả ra file: BAI23.OUT
- Dòng đầu tiên ghi số lượng các số có dạng 5*k + 7 tìm được.
- Dịng thứ hai, ghi lần lượt các số có dạng 5*k + 7, theo thứ tự tăng dần các số
cách nhau một khoảng trắng.
- Dòng thứ ba, ghi lại dãy số sao cho các số trong dãy đôi một khác nhau, theo thứ
tự tăng dần (tỉa mảng).
Ví dụ:
BAI23.INP
BAI23.OUT
Giải thích
5
4
Trong các số đã cho ta có:

107 27 57 27 24 27 27 57 107
27 = 5*4 + 7, với k = 4
24 27 57 107
57 = 5*10 + 7, với k = 10
107 = 5*20 + 7, với k = 20
⸙Thuật toán:
ↈCode tham khảo:
1 #đọc dữ liệu từ file INP
with open('bai23.inp') as fi:


21
n = int(fi.readline())
2
a=list(map(int,fi.readline().split()))
3
4 #Thuật toán và ghi file OUT
5 with open('bai23.out','w') as fo:
b=[]
6
for i in a:
7
if (i-7)%5==0: b.append(i)
8
print(len(b),file=fo)
9
b.sort()
10
for i in b:
11

print(i,end=' ',file=fo)
12
print(file=fo)
13
a=list(set(a))
14
a.sort()
15
for i in a:
16
print(i,end=' ',file=fo)
17
☼Tìm hiểu thêm:



×