Giải Tin Học 10 trang 152

Lời giải chi tiết SGK Lớp 10 · Môn Tin Học · Trang 152–153

Nguon: Tin Hoc 10 - Ket Noi Tri Thuc Voi Cuoc Song (trang 152 – 153)

🔍 Kiến thức cần nhớ

Phần lý thuyết ở các trang này trình bày bài thực hành giải phương trình và giới thiệu cấu trúc rẽ nhánh mở rộng.

1. Cấu trúc if ... elif ... else

Khi các lệnh rẽ nhánh lồng nhau, ta có thể viết gọn lại bằng elif:

# Dạng lồng nhau (dài dòng)
if <điều kiện 1>:
    
else:
    if <điều kiện 2>:
        
    else:
        

# Dạng viết gọn với elif
if <điều kiện 1>:
    
elif <điều kiện 2>:
    
else:
    
💡 Mẹo nhớ: elif = "else if". Dùng elif giúp chương trình ngắn gọn, dễ đọc và tránh thụt lề (indent) quá sâu. Cấu trúc if ... elif ... else có thể lồng nhau nhiều lần.

2. Cách biện luận phương trình ax² + bx + c = 0

  • Nếu a = b = c = 0: phương trình có vô số nghiệm
  • Nếu a = b = 0; c ≠ 0: phương trình vô nghiệm
  • Nếu a = 0; b ≠ 0: phương trình bậc nhất, có nghiệm duy nhất x = -c/b
  • Nếu a ≠ 0: phương trình bậc hai, xét delta = b² - 4ac:
  • delta < 0: vô nghiệm
  • delta = 0: nghiệm kép x = -b/(2a)
  • delta > 0: hai nghiệm phân biệt x = (-b ± √delta)/(2a)
⚠️ Lưu ý thi: Khi viết hàm trong Python phải định nghĩa hàm (def) trước khi gọi. Hàm GiaiPT2 gọi lại hàm GiaiPT1 khi a = 0 — đây là kỹ thuật tái sử dụng hàm rất hay được hỏi.

⚙️ Bài tập

LUYỆN TẬP

Câu 1

Đề bài: Viết chương trình yêu cầu nhập số thực dương a. Chương trình cần kiểm tra dữ liệu nhập như sau: Nếu số đã nhập nhỏ hơn hoặc bằng 0 thì thông báo: "Nhập sai, số a phải lớn hơn 0. Hãy nhập lại". Chương trình chỉ dừng sau khi người dùng nhập đúng.

Cách 1 — Dùng vòng lặp while với điều kiện kiểm tra

Ý tưởng: lặp lại việc nhập cho đến khi nào số nhập vào lớn hơn 0 thì dừng.

# Nhập số thực dương, kiểm tra cho đến khi nhập đúng
a = float(input("Nhập số thực dương a: "))
while a <= 0:
    print("Nhập sai, số a phải lớn hơn 0. Hãy nhập lại")
    a = float(input("Nhập số thực dương a: "))

print("Bạn đã nhập đúng. a =", a)

Giải thích từng bước:

  • Lần đầu nhập a từ bàn phím.
  • Vòng while a <= 0 kiểm tra: nếu a còn nhỏ hơn hoặc bằng 0 thì thông báo lỗi và bắt nhập lại.
  • Khi a > 0, điều kiện a <= 0 sai → thoát vòng lặp.
Cách 2 — Dùng while True kết hợp break
while True:
    a = float(input("Nhập số thực dương a: "))
    if a > 0:
        break          # nhập đúng thì thoát
    print("Nhập sai, số a phải lớn hơn 0. Hãy nhập lại")

print("Bạn đã nhập đúng. a =", a)
💡 Mẹo nhớ: Mẫu while True ... break rất tiện khi cần "lặp cho đến khi điều kiện thỏa mãn" mà chỉ phải viết lệnh nhập một lần (không lặp lại lệnh input như Cách 1).

Câu 2

Đề bài: Viết chương trình in bảng cửu chương ra màn hình như sau:

  • Hàng thứ nhất in ra bảng nhân 1, 2, 3, 4, 5.
  • Hàng thứ hai in ra bảng nhân 6, 7, 8, 9, 10.
Cách 1 — Dùng hai vòng lặp for lồng nhau

Mỗi "hàng" ở đây là một dòng kết quả của phép nhân (ví dụ dòng "1 x 1 = 1, 2 x 1 = 2, ..."). Ta dùng:

  • Vòng ngoài chạy theo thừa số thứ hai i từ 1 đến 10.
  • Vòng trong chạy theo bảng nhân j (nhóm 1–5 và nhóm 6–10).
# In bảng nhân 1 -> 5 (khối thứ nhất)
print("Bảng nhân 1, 2, 3, 4, 5:")
for i in range(1, 11):
    for j in range(1, 6):
        print(j, "x", i, "=", j * i, end="\t")
    print()   # xuống dòng sau mỗi hàng

print()

# In bảng nhân 6 -> 10 (khối thứ hai)
print("Bảng nhân 6, 7, 8, 9, 10:")
for i in range(1, 11):
    for j in range(6, 11):
        print(j, "x", i, "=", j * i, end="\t")
    print()

Giải thích:

  • range(1, 6) cho j = 1, 2, 3, 4, 5 (khối nhân thứ nhất).
  • range(6, 11) cho j = 6, 7, 8, 9, 10 (khối nhân thứ hai).
  • end="\t" để các phép nhân nằm trên cùng một dòng, ngăn cách bằng dấu tab.
  • print() (rỗng) để xuống dòng sau khi in hết một hàng.
Cách 2 — Gộp bằng một hàm in bảng theo nhóm
def in_bang(bat_dau, ket_thuc):
    print("Bảng nhân", bat_dau, "đến", ket_thuc - 1, ":")
    for i in range(1, 11):
        for j in range(bat_dau, ket_thuc):
            print(j * i, end="\t")
        print()
    print()

in_bang(1, 6)    # bảng nhân 1, 2, 3, 4, 5
in_bang(6, 11)   # bảng nhân 6, 7, 8, 9, 10
⚠️ Lưu ý thi: Phân biệt rõ phạm vi range(a, b) chạy từ a đến b - 1. Đây là lỗi sai phổ biến nhất khi làm việc với vòng lặp.

VẬN DỤNG

Câu 1

Đề bài: Viết chương trình nhập hai số tự nhiên Y1, Y2 là số năm, Y2 > Y1. Tính xem trong khoảng thời gian từ năm Y1 đến năm Y2 có bao nhiêu năm nhuận. Áp dụng tính xem trong thế kỉ XXI có bao nhiêu năm nhuận.

Quy tắc năm nhuận: Một năm là năm nhuận nếu:

  • Chia hết cho 4 không chia hết cho 100, hoặc
  • Chia hết cho 400.
Cách 1 — Duyệt qua từng năm và đếm
Y1 = int(input("Nhập năm bắt đầu Y1: "))
Y2 = int(input("Nhập năm kết thúc Y2: "))

dem = 0
for nam in range(Y1, Y2 + 1):
    if (nam % 4 == 0 and nam % 100 != 0) or (nam % 400 == 0):
        dem = dem + 1

print("Số năm nhuận từ", Y1, "đến", Y2, "là:", dem)

Giải thích:

  • range(Y1, Y2 + 1) để duyệt cả hai mốc Y1 và Y2.
  • Điều kiện kiểm tra năm nhuận đúng theo quy tắc lịch Gregorian.

Áp dụng cho thế kỉ XXI (từ năm 2001 đến năm 2100):

Ta đếm các năm chia hết cho 4 trong khoảng 2001–2100 là: 2004, 2008, ..., 2100 — tổng cộng 25 năm. Nhưng năm 2100 chia hết cho 100 mà không chia hết cho 400 nên không phải năm nhuận.

→ Thế kỉ XXI có 24 năm nhuận.

# Kiểm tra lại bằng chương trình
dem = 0
for nam in range(2001, 2101):
    if (nam % 4 == 0 and nam % 100 != 0) or (nam % 400 == 0):
        dem = dem + 1
print("Thế kỉ XXI có", dem, "năm nhuận")   # Kết quả: 24
Cách 2 — Tính nhanh bằng công thức đếm bội số

Số năm nhuận từ 1 đến n = (số năm chia hết cho 4) − (số chia hết cho 100) + (số chia hết cho 400).

Đặt f(n) = n//4 − n//100 + n//400. Khi đó số năm nhuận trong [Y1, Y2] = f(Y2) − f(Y1 − 1).

def f(n):
    return n // 4 - n // 100 + n // 400

Y1 = int(input("Nhập năm bắt đầu Y1: "))
Y2 = int(input("Nhập năm kết thúc Y2: "))
print("Số năm nhuận:", f(Y2) - f(Y1 - 1))

Kiểm tra với thế kỉ XXI: f(2100) − f(2000) = (525 − 21 + 5) − (500 − 20 + 5) = 509 − 485 = 24. Khớp với kết quả trên.

💡 Mẹo nhớ: Năm tròn thế kỉ (2000, 2100, 2200, 2300...) chỉ là năm nhuận khi chia hết cho 400. Ví dụ: 2000 là năm nhuận, còn 1900 và 2100 thì không.

Câu 2

Đề bài: Gọi ƯCLN(a, b) là hàm tính ước chung lớn nhất của hai số tự nhiên a, b. Dễ thấy ƯCLN(a, b) = ƯCLN(b, a%b) nếu b > 0 và ƯCLN(a, 0) = a. Từ đó hãy viết chương trình nhập hai số a, b và tính ƯCLN của a và b.

Đây chính là thuật toán Euclid dựa trên phép chia có dư.

Cách 1 — Dùng đệ quy (đúng theo công thức đề bài)

Công thức đề cho có dạng đệ quy:

  • ƯCLN(a, 0) = a (trường hợp dừng)
  • ƯCLN(a, b) = ƯCLN(b, a%b) khi b > 0
def UCLN(a, b):
    if b == 0:
        return a
    else:
        return UCLN(b, a % b)

a = int(input("Nhập số a: "))
b = int(input("Nhập số b: "))
print("ƯCLN của", a, "và", b, "là:", UCLN(a, b))

Giải thích với ví dụ a = 48, b = 36:

  • ƯCLN(48, 36) = ƯCLN(36, 12) (vì 48 % 36 = 12)
  • ƯCLN(36, 12) = ƯCLN(12, 0) (vì 36 % 12 = 0)
  • ƯCLN(12, 0) = 12 (gặp trường hợp dừng)

→ Kết quả là 12.

Cách 2 — Dùng vòng lặp while (không đệ quy)
def UCLN(a, b):
    while b != 0:
        a, b = b, a % b
    return a

a = int(input("Nhập số a: "))
b = int(input("Nhập số b: "))
print("ƯCLN của", a, "và", b, "là:", UCLN(a, b))

Giải thích:

  • Mỗi vòng lặp gán lại a = bb = a%b (phép gán đồng thời trong Python).
  • Khi b = 0, vòng lặp dừng, giá trị a hiện tại chính là ƯCLN.
  • Cách này tiết kiệm bộ nhớ hơn đệ quy vì không phải gọi hàm nhiều lần.
⚠️ Lưu ý thi: Phép gán đồng thời a, b = b, a % b thực hiện đúng vì Python tính toàn bộ vế phải trước rồi mới gán. Nếu tách thành hai dòng riêng (gán a trước, rồi gán b) sẽ cho kết quả sai vì giá trị a đã bị thay đổi.

🎯 Ghi nhớ: - Mẫu while True ... break rất tiện để "lặp đến khi nhập đúng". - range(a, b) chạy từ a đến b − 1 — luôn nhớ cộng 1 khi cần lấy cả cận trên. - Năm nhuận: chia hết cho 4 nhưng không chia hết cho 100, hoặc chia hết cho 400. Thế kỉ XXI có 24 năm nhuận. - Thuật toán Euclid tính ƯCLN: ƯCLN(a, b) = ƯCLN(b, a%b), dừng khi b = 0. Viết được cả bằng đệ quy lẫn vòng lặp while.
Chế độ đọc sách →