CÂU LỆNH LẶP TRONG C++
Chào các bạn học sinh và lập trình viên! Khi giải quyết các bài toán lập trình trên Sen Code Online Judge!, chúng ta thường gặp các yêu cầu cần phải thực hiện đi thực hiện lại một hành động nhiều lần. Ví dụ như tính tổng các số từ 1 đến N, tìm các số nguyên tố trong một khoảng, hay duyệt qua các phần tử của một mảng.
Thay vì viết hàng ngàn dòng code giống nhau, C++ cung cấp cấu trúc lặp giúp giải quyết việc này một cách tối ưu và ngắn gọn. C++ có ba câu lệnh lặp chính: for, while và do-while. Bài viết này sẽ hướng dẫn chi tiết cú pháp, nguyên lý hoạt động và các ví dụ minh họa sinh động.
1. Vòng lặp while (Vòng lặp kiểm tra trước)
Khái niệm:
Vòng lặp while thường được sử dụng khi chúng ta chưa biết trước chính xác số lần lặp, mà số lần lặp phụ thuộc vào một điều kiện cụ thể. Điều kiện sẽ được kiểm tra trước khi thực thi khối lệnh bên trong.
Cú pháp:
while (điều_kiện) {
// Khối lệnh lặp được thực thi khi điều_kiện đúng (true)
}
Nguyên lý hoạt động:
- Máy tính kiểm tra
điều_kiện. - Nếu
điều_kiệnđúng (true), khối lệnh bên trong{}sẽ được thực thi. Sau đó quay lại bước 1. - Nếu
điều_kiệnsai (false), vòng lặp kết thúc, chương trình nhảy xuống câu lệnh tiếp theo sau khốiwhile.
Lưu ý: Bên trong khối lệnh lặp phải có câu lệnh làm thay đổi trạng thái của điều kiện để điều kiện hướng tới kết quả false, nếu không vòng lặp sẽ chạy vô hạn (lặp vô tận).
Ví dụ minh họa:
Viết chương trình nhập vào một số nguyên dương N. Tính tổng các chữ số của N. (Ví dụ N = 1234 có tổng các chữ số là 1 + 2 + 3 + 4 = 10).
#include <bits/stdc++.h>
using namespace std;
int main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
long long N;
cin >> N;
int tongChuSo = 0;
// Vòng lặp while kiểm tra điều kiện N > 0
while (N > 0) {
int chuSoCuoi = N % 10; // Lấy chữ số cuối cùng của N
tongChuSo += chuSoCuoi; // Cộng tích lũy vào tổng
N /= 10; // Loại bỏ chữ số cuối cùng (giúp N nhỏ dần về 0)
}
cout << tongChuSo << "\n";
return 0;
}
Giải tích chi tiết:
- Giả sử nhập N = 123.
- Lượt lặp 1: Điều kiện
N > 0(123 > 0) đúng. Lấy123 % 10 = 3,tongChuSo = 0 + 3 = 3, chiaN = 123 / 10 = 12. - Lượt lặp 2: Điều kiện
N > 0(12 > 0) đúng. Lấy12 % 10 = 2,tongChuSo = 3 + 2 = 5, chiaN = 12 / 10 = 1. - Lượt lặp 3: Điều kiện
N > 0(1 > 0) đúng. Lấy1 % 10 = 1,tongChuSo = 5 + 1 = 6, chiaN = 1 / 10 = 0. - Lượt lặp 4: Điều kiện
N > 0(0 > 0) sai. Vòng lặp dừng lại.
- Lượt lặp 1: Điều kiện
- Kết quả hiển thị là 6. Vòng lặp đã dừng một cách an toàn nhờ phép toán
N /= 10.
2. Vòng lặp do-while (Vòng lặp kiểm tra sau)
Khái niệm:
Vòng lặp do-while tương tự như while, nhưng có một điểm khác biệt cốt lõi: Khối lệnh lặp luôn được thực thi ít nhất một lần trước khi điều kiện được kiểm tra.
Cú pháp:
do {
// Khối lệnh lặp (luôn chạy ít nhất 1 lần đầu tiên)
} while (điều_kiện); // Chú ý có dấu chấm phẩy ở cuối
Nguyên lý hoạt động:
- Máy tính thực thi khối lệnh bên trong
dotrước. - Kiểm tra
điều_kiện. - Nếu
điều_kiệnđúng, quay lại thực thi khối lệnh. - Nếu
điều_kiệnsai, vòng lặp dừng lại.
Ví dụ minh họa:
Yêu cầu người dùng nhập một số nguyên dương đại diện cho bán kính R của hình tròn từ bàn phím. Nếu người dùng nhập sai (bán kính <= 0), yêu cầu nhập lại cho đến khi nhập đúng số dương.
#include <bits/stdc++.h>
using namespace std;
int main() {
// Không dùng Fast I/O ở bài toán tương tác trực tiếp
double R;
do {
cout << "Nhap ban kinh R (R > 0): ";
cin >> R;
if (R <= 0) {
cout << "Ban kinh khong hop le! Vui long nhap lai.\n";
}
} while (R <= 0); // Lặp lại việc nhập nếu R vẫn <= 0
double dienTich = 3.14159 * R * R;
cout << "Dien tich hinh tron: " << dienTich << "\n";
return 0;
}
3. Vòng lặp for (Vòng lặp xác định số lần lặp)
Khái niệm:
Vòng lặp for thường được sử dụng khi chúng ta đã biết trước chính xác số lần lặp của chương trình. Nó gộp cả 3 thao tác: khởi tạo, kiểm tra điều kiện và cập nhật biến lặp vào cùng một dòng lệnh để code cực kỳ ngắn gọn và dễ quản lý.
Cú pháp:
for (khởi_tạo_biến_lặp; điều_kiện_dừng; cập_nhật_biến_lặp) {
// Khối lệnh lặp
}
Nguyên lý hoạt động:
- Thực hiện lệnh
khởi_tạo_biến_lặp(chỉ chạy duy nhất 1 lần đầu tiên khi bắt đầu vòng lặp). - Kiểm tra
điều_kiện_dừng. Nếu sai, vòng lặp kết thúc ngay lập tức. - Nếu đúng, thực thi toàn bộ khối lệnh bên trong
{}. - Thực hiện lệnh
cập_nhật_biến_lặp(ví dụi++). - Quay lại bước 2 để tiếp tục kiểm tra điều kiện.
Ví dụ minh họa:
Viết chương trình nhập vào số nguyên dương K. In ra bảng cửu chương của K (từ 1 đến 10).
#include <bits/stdc++.h>
using namespace std;
int main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
int K;
cin >> K;
// Vòng lặp for chạy biến i từ 1 đến 10
for (int i = 1; i <= 10; ++i) {
cout << K << " x " << i << " = " << K * i << "\n";
}
return 0;
}
4. Các câu lệnh điều khiển vòng lặp: break và continue
Trong quá trình vòng lặp đang chạy, đôi khi chúng ta cần thay đổi luồng hoạt động thông thường của nó. C++ cung cấp hai lệnh hỗ trợ:
- Lệnh
break: Lập tức kết thúc và thoát hoàn toàn ra ngoài vòng lặp chứa nó (bất kể điều kiện vòng lặp vẫn đang đúng). - Lệnh
continue: Bỏ qua toàn bộ các câu lệnh còn lại nằm phía dưới nó trong lượt lặp hiện tại để chuyển ngay sang lượt lặp tiếp theo (thực hiện kiểm tra điều kiện hoặc cập nhật biến lặp).
Ví dụ minh họa break và continue:
In ra các số chia hết cho 3 trong khoảng từ 1 đến 15, nhưng nếu gặp số 12 thì dừng vòng lặp ngay lập tức.
#include <bits/stdc++.h>
using namespace std;
int main() {
for (int i = 1; i <= 15; ++i) {
if (i == 12) {
break; // Thoát hẳn vòng lặp khi i = 12
}
if (i % 3 != 0) {
continue; // Bỏ qua lệnh in phía dưới nếu i không chia hết cho 3
}
cout << i << " ";
}
cout << "\n";
return 0;
}
Kết quả in ra: 3 6 9 (số 12 bị ngắt hoàn toàn bởi lệnh break, số 15 không bao giờ đạt tới).
5. ĐỀ XUẤT 10 BÀI TẬP THỰC HÀNH THỰC TẾ (CẤU TRÚC LẶP VÀ TOÁN HỌC)
Dưới đây là 10 bài toán ứng dụng vòng lặp kết hợp các kiến thức toán học nền tảng thường gặp trong lập trình thi đấu:
Bài 1: Tính giai thừa xếp hàng
- Ngữ cảnh: Một nhà hàng cần sắp xếp thứ tự phục vụ cho N khách VIP vào bàn tiệc dài. Số cách sắp xếp chính là hoán vị của N phần tử, tương đương với công thức tính giai thừa: N! = 1 * 2 * 3 * ... * N.
- Yêu cầu: Tính giá trị N! của số nguyên dương N.
- Đầu vào (Input): Một số nguyên duy nhất N (1 <= N <= 15) (N nhỏ để tránh tràn số kiểu dữ liệu).
- Đầu ra (Output): Một số nguyên duy nhất là kết quả của N!.
- Ví dụ:
- Input:
5 - Output:
120
- Input:
Bài 2: Kiểm tra số nguyên tố mật mã
- Ngữ cảnh: Một số nguyên tố là số nguyên lớn hơn 1 và chỉ có duy nhất hai ước là 1 và chính nó. Trong mật mã học, số nguyên tố đóng vai trò then chốt để bảo mật thông tin.
- Yêu cầu: Kiểm tra xem số nguyên dương N nhập từ bàn phím có phải là số nguyên tố không.
- Mẹo tối ưu: Chỉ cần kiểm tra xem N có ước nào trong khoảng từ 2 đến cănbậchai(N) hay không. Nếu có thì N không phải là số nguyên tố.
- Đầu vào (Input): Một số nguyên duy nhất N (1 <= N <= 109).
- Đầu ra (Output): In ra
YESnếu N là số nguyên tố, ngược lại in raNO. - Ví dụ:
- Input:
97 - Output:
YES
- Input:
Bài 3: Đếm số lượng số nguyên tố trong khoảng
- Ngữ cảnh: Một quản trị viên cần thống kê xem trong khoảng từ số nguyên A đến số nguyên B có bao nhiêu số nguyên tố để phân tích tần suất phân bố mật mã bảo mật.
- Yêu cầu: Đếm số lượng số nguyên tố trong đoạn [A, B].
- Đầu vào (Input): Một dòng gồm hai số nguyên dương A và B (1 <= A <= B <= 105).
- Đầu ra (Output): Một số nguyên duy nhất biểu thị số lượng số nguyên tố tìm thấy.
- Ví dụ:
- Input:
10 20 - Output:
4(Các số nguyên tố là 11, 13, 17, 19)
- Input:
Bài 4: Số cách chọn ban cán sự lớp (Tổ hợp)
- Ngữ cảnh: Một lớp học gồm N học sinh. Giáo viên cần chọn ra một nhóm gồm K học sinh để làm ban tự quản lớp. Số cách chọn khác nhau được tính theo công thức Tổ hợp chập K của N: CNK = N! / (K! * (N - K)!)
- Yêu cầu: Tính giá trị CNK.
- Đầu vào (Input): Một dòng chứa hai số nguyên N và K (1 <= N <= 30, 0 <= K <= N) sao cho kết quả nằm trong giới hạn kiểu
long long. - Đầu ra (Output): Một số nguyên duy nhất là kết quả của phép tổ hợp.
- Ví dụ:
- Input:
5 2 - Output:
10
- Input:
Bài 5: Phân công nhiệm vụ nhân sự (Chỉnh hợp)
- Ngữ cảnh: Một công ty có N nhân viên ưu tú. Người quản lý cần phân công K công việc khác nhau cho K nhân viên (mỗi công việc giao cho đúng một người). Số cách phân công nhiệm vụ khác nhau được tính theo công thức Chỉnh hợp chập K của N: ANK = N! / (N - K)!
- Yêu cầu: Tính giá trị ANK.
- Đầu vào (Input): Một dòng chứa hai số nguyên N và K (1 <= N <= 15, 0 <= K <= N).
- Đầu ra (Output): Một số nguyên duy nhất là kết quả phép chỉnh hợp.
- Ví dụ:
- Input:
5 2 - Output:
20
- Input:
Bài 6: Tìm ước chung lớn nhất (GCD)
- Ngữ cảnh: Một kiến trúc sư có một tấm gỗ dài A cm và rộng B cm. Bác muốn cắt toàn bộ tấm gỗ thành các tấm hình vuông bằng nhau có kích thước lớn nhất có thể mà không để lại gỗ thừa.
- Yêu cầu: Tìm kích thước cạnh hình vuông lớn nhất đó (bản chất là tìm Ước chung lớn nhất của A và B bằng thuật toán Euclid).
- Đầu vào (Input): Một dòng chứa hai số nguyên dương A và B (1 <= A, B <= 109).
- Đầu ra (Output): Một số nguyên duy nhất là ước chung lớn nhất của A và B.
- Ví dụ:
- Input:
24 36 - Output:
12
- Input:
Bài 7: Số thỏ sinh sản (Số Fibonacci)
- Ngữ cảnh: Một nhà sinh vật học nghiên cứu sự sinh sản của một cặp thỏ theo quy luật:
- Tháng thứ 1 và tháng thứ 2 có 1 cặp thỏ.
- Từ tháng thứ 3 trở đi, số cặp thỏ ở tháng thứ N bằng tổng số cặp thỏ của hai tháng trước đó cộng lại: FN = FN-1 + FN-2.
- Yêu cầu: Tìm số lượng cặp thỏ ở tháng thứ N.
- Đầu vào (Input): Một số nguyên duy nhất N (1 <= N <= 50).
- Đầu ra (Output): Một số nguyên duy nhất là số cặp thỏ ở tháng thứ N.
- Ví dụ:
- Input:
6 - Output:
8(Dãy số là 1, 1, 2, 3, 5, 8)
- Input:
Bài 8: Kiểm tra số hoàn hảo
- Ngữ cảnh: Trong toán học cổ đại, một số nguyên dương được gọi là số hoàn hảo nếu tổng tất cả các ước thực sự của nó (ngoại trừ chính nó) bằng chính số đó. Ví dụ số 6 có các ước thực sự là 1, 2, 3 và 1 + 2 + 3 = 6.
- Yêu cầu: Kiểm tra xem số nguyên dương N có phải là số hoàn hảo hay không.
- Đầu vào (Input): Một số nguyên dương N (1 <= N <= 105).
- Đầu ra (Output): In ra
YESnếu N là số hoàn hảo, ngược lại in raNO. - Ví dụ:
- Input:
28 - Output:
YES(Ước thực sự của 28 là 1, 2, 4, 7, 14 và 1+2+4+7+14 = 28)
- Input:
Bài 9: Phân tích thừa số nguyên tố mật mã RSA
- Ngữ cảnh: Để giải mã một hệ thống bảo mật, ta cần phân tích khóa số nguyên dương N thành các thừa số nguyên tố cơ bản.
- Yêu cầu: Phân tích N thành tích các thừa số nguyên tố theo thứ tự tăng dần.
- Đầu vào (Input): Một số nguyên dương N (2 <= N <= 107).
- Đầu ra (Output): In ra dãy các thừa số nguyên tố cách nhau một khoảng trắng.
- Ví dụ:
- Input:
12 - Output:
2 2 3
- Input:
Bài 10: Tích lũy tiền tiết kiệm gửi ngân hàng
- Ngữ cảnh: An gửi tiết kiệm số tiền gốc ban đầu là M đồng vào ngân hàng với lãi suất lãi kép là R% mỗi tháng. Nghĩa là sau mỗi tháng, tiền lãi nhận được sẽ cộng dồn trực tiếp vào tiền gốc để tính lãi cho tháng kế tiếp.
- Yêu cầu: Hãy tính xem sau tối thiểu bao nhiêu tháng, tổng số tiền cả gốc lẫn lãi của An sẽ đạt tối thiểu T đồng.
- Đầu vào (Input): Một dòng gồm số thực M (tiền gốc), số thực R (lãi suất %) và số thực T (tiền mục tiêu) (1 <= M <= T <= 109, 0.1 <= R <= 10.0).
- Đầu ra (Output): Một số nguyên duy nhất là số tháng tối thiểu cần thiết.
- Ví dụ:
- Input:
100.0 5.0 120.0 - Output:
4(Tháng 1: 105.0đ, Tháng 2: 110.25đ, Tháng 3: 115.76đ, Tháng 4: 121.55đ)
- Input:
Lời kết
Việc kết hợp linh hoạt vòng lặp for, while và do-while giúp bạn giải quyết được tất cả các bài toán yêu cầu xử lý dữ liệu quy mô lớn và lặp đi lặp lại. Hãy nắm chắc các thuật toán toán học cơ bản như kiểm tra số nguyên tố và tính giai thừa vì đây là những viên gạch đầu tiên của lập trình thi đấu.
Hãy viết mã nguồn và nộp bài giải của 10 bài tập vòng lặp trên tại hệ thống Sen Code Online Judge! nhé! Chúc các bạn học tập thật tốt!
Bình luận