Hướng dẫn giải của Số may mắn (Đề Quảng Trị 2021)
Nộp một lời giải chính thức trước khi tự giải là một hành động có thể bị ban.
Hướng dẫn giải
Với mỗi số ~N~, lặp việc cộng các chữ số cho đến khi còn một chữ số (gọi là kết quả cuối). Nếu kết quả cuối bằng ~M~ thì người chơi trúng thưởng, in 1; ngược lại in 0. Số ~N~ có tới ~100~ chữ số nên không thể lưu bằng kiểu số nguyên thông thường; mọi xử lý đều làm trên chuỗi.
Sub 1: Vét cạn — lặp cộng chữ số trên chuỗi
Với mỗi số, cộng các chữ số trong chuỗi, biến tổng thành chuỗi mới, rồi lặp lại đến khi chuỗi chỉ còn một ký tự. Cách này làm đúng với mọi số vì chỉ dùng chuỗi. Nếu chỉ nộp sub này: đúng 20/20 test.
Sub 2: Tính nhanh bằng số dư cho 9 — ~O(\text{độ dài } N)~
Với ~N > 0~, kết quả cuối là ~9~ nếu ~N~ chia hết cho 9, ngược lại là ~N \bmod 9~. Số dư ~N \bmod 9~ tính được ngay bằng cách cộng các chữ số rồi lấy dư cho 9, không cần lặp. Bẫy cần chú ý: trường hợp chia hết cho 9 phải cho kết quả 9, không phải 0. Nếu chỉ nộp sub này: đúng 20/20 test.
Chương trình hoàn chỉnh
main đọc ~K~, ~M~ và ~K~ chuỗi số. Nếu ~K \le 100~ gọi sub1, còn lại gọi sub2. Đầu main có freopen vì máy chấm đọc/ghi file CAU3.INP, CAU3.OUT.
#include <bits/stdc++.h>
using namespace std;
int K;
long long M;
vector<string> nums; // cac so N duoc giu duoi dang chuoi (co the rat dai, toi 100 chu so)
// Sub 1: vet can - voi moi so, lap viec cong cac chu so (tren chuoi) cho den khi con mot chu so.
// Cach nay dung cho moi so vi khong bao gio can so lon.
void sub1() {
for (int i = 0; i < K; i++) {
string s = nums[i];
while (s.size() > 1) {
int t = 0;
for (char c : s) t += c - '0';
s = to_string(t); // tong cac chu so moi
}
cout << (s[0] - '0' == M ? 1 : 0) << "\n";
}
}
// Sub 2: dung tinh chat chia 9 - voi N > 0 thi chu so cuoi cung la (N mod 9), neu chia het cho 9 thi la 9.
// Tinh N mod 9 bang cach cong cac chu so mod 9 nen chay O(do dai) cho moi so, khong can lap.
void sub2() {
for (int i = 0; i < K; i++) {
int r = 0;
for (char c : nums[i]) r = (r + (c - '0')) % 9;
int root = (r == 0) ? 9 : r;
cout << (root == M ? 1 : 0) << "\n";
}
}
int main() {
freopen("CAU3.INP", "r", stdin); // may cham doc/ghi file
freopen("CAU3.OUT", "w", stdout);
cin >> K >> M;
nums.resize(K);
for (int i = 0; i < K; i++) cin >> nums[i];
// Moi so co toi 100 chu so nen sub2 (chia 9) la cach nhanh nhat; du lieu nho van dung sub1
if (K <= 100) sub1();
else sub2();
return 0;
}
Bình luận