# THI THỬ MÔN CHUYÊN - 2025 - SỞ GD-ĐT >[!Note] Thông tin >Sau đây là lời giải của Kỳ thi thử môn chuyên TS10 vào trường THPT chuyên Lê Quý Đôn tỉnh Bà Rịa - Vũng Tàu. > >**Thời gian:** Ngày 28/04/2025 > >**Bạn đọc có thể nộp và chấm bài** [TẠI ĐÂY](https://chuyentinbrvt.online/contest/algi_mockhsg9lan2_2025) > >:::info >Chuẩn bị bởi ==team Logica==, thuộc khuôn khổ dự án [**The Algitect (ALGI Project)**](https://www.facebook.com/algitect.project) >::: [toc] ## Bài 1: Số chính phương (5 điểm) ### Tóm tắt đề bài: Cho số nguyên dương $n$. **Yêu cầu:** Tìm số chính phương $x$ sao cho |$n - x$| nhỏ nhất, trong trường hợp có $2$ số chính phương cùng thỏa mãn điều kiện thì cho biết ==số chính phương có giá trị nhỏ nhất==. **Dữ liệu đảm bảo:** $1 \le n \le 10^9$. **Subtasks:** - $60\%$ số điểm tương ứng với $1 \le n \le 10^6$. - $40\%$ số điểm không có ràng buộc gì thêm. ### Subtask 1 Duyệt số $i$ tăng dần từ $1$, kiểm tra số $i$ có phải là số chính phương hay không và lấy đáp án. **Lưu ý:** Ta chỉ duyệt đến ==số chính phương đầu tiên lớn hơn $n$==, các số sau đó không có ý nghĩa. **Độ phức tạp thời gian:** $O \left( \left \lceil \sqrt n \right \rceil ^ 2 \right)$. ### Subtask 2 >[!Tip] > Số $x$ là số chính phương khi và chỉ khi $x = k^2$ với $k \in N$. Dễ thấy, đáp án của bài toán chỉ có thể là một trong hai số sau đây: - Số chính phương $l$ ==lớn nhất bé hơn hoặc bằng $n$==. - Số chính phương $r$ ==nhỏ nhất lớn hơn hoặc bằng $n$==. Ta có: $l \le n$ với $k \in N$. Do đó $\sqrt l \le \sqrt n$, mà $\sqrt l \in N$ (vì $l$ là số chính phương) nên: $$ \begin{flalign} \sqrt l = \left \lfloor \sqrt n \right \rfloor\\ \Rightarrow l = \left \lfloor \sqrt n \right \rfloor ^ 2 \end{flalign} $$ Tương tự, ta có: $$ r = \left \lceil \sqrt n \right \rceil ^ 2 $$ **Đáp án:** - $l$, nếu $n - l \le r - n$. - $r$, nếu $n - l \gt r - n$. **Độ phức tạp thời gian:** $O \left( \log n \right)$. > Độ phức tạp trên là độ phức tạp của lệnh `sqrt()` của C++. :::success :::spoiler Code ```cpp=1 #include <bits/stdc++.h> using namespace std; int main() { int n; cin >> n; int l = (int)sqrt(n); int r = l + 1; if (n - l*l <= r*r - n) cout << l*l; else cout << r*r; return 0; } ``` ::: ## Bài 2: Số may mắn (5 điểm) ### Tóm tắt đề bài: Một số nguyên dương được gọi là ==số may mắn== nếu tổng các chữ số chia hết cho $9$. >Ví dụ: $9, 18$ và $2007$ là các ==số may mắn==. **Yêu cầu:** Cho số nguyên dương $n$, tính tổng tất cả các ==số may mắn== từ $1$ đến $n$. **Dữ liệu đảm bảo:** $1 \le n \le 10^9$. **Subtasks:** - $50\%$ tests tương ứng $n \le 10^6$. - $50\%$ tests tương ứng $10^6 < n \le 10^9$. ### Lời giải: ### Subtask 1 Duyệt qua mọi số từ $1$ đến $n$, tính tổng các chữ số và kiểm tra có chia hết cho $9$ không, nếu có thì cộng thêm vào kết quả. **Độ phức tạp thời gian:** $O \left( n \right)$. ### Subtask 2 >[!Tip] Nhận xét > Các số có tổng chữ số chia hết cho 9 cũng chia hết cho 9. > > Không mất tính tổng quát, giả sử số $n$ có dạng $\overline{abcd}$ và $(a + b + c + d) \bmod 9 = 0$. > Ta có: > $$ > \begin{flalign} > n &= 1000a + 100b + 10c + d \\ > &= 999a + a + 99b + b + 9c + c + d \\ > &= (999a + 99b + 9c) + (a + b + c + d) > \end{flalign} > $$ > Dễ thấy, $(999a + 99b + 9c) \bmod 9 = 0$, mà $(a + b + c + d) \bmod 9 = 0$ (đề cho). Như vậy, $n$ chia hết cho $9$. Bài toán trở thành ==tính tổng các số chia hết cho 9 từ $1$ đến $n$==. Có thể thấy, các số chia hết cho $9$ từ $1$ đến $n$ có dạng: $$ 9, 9 \times 2, 9 \times 3, \dots, 9 \times (k-1), 9 \times k \; (9 \times k \le n) $$ Ta có: $k = \left \lfloor \frac n 9 \right \rfloor$. Như vậy, đáp án của bài là: $$ \begin{flalign} 9 + 9 \times 2 + 9 \times 3 + \dots + 9 \times (k-1) + 9 \times k \\ = 9 \times (1 + 2 + 3 + \dots + k) \\ = 9 \times \frac{k \times (k+1)}2 \end{flalign} $$ > Hoặc áp dụng [công thức tính tổng cấp số cộng](https://vietjack.com/tai-lieu-mon-toan/cac-cong-thuc-ve-cap-so-cong-ctqt11.jsp) nếu bạn nhớ. **Độ phức tạp thời gian:** $O \left( 1 \right)$. :::success :::spoiler Code ```cpp=1 #include <bits/stdc++.h> using namespace std; int main() { long long n; cin >> n; n /= 9; cout << 9*n*(n+1)/2; return 0; } ``` ::: ## Bài 3: Đếm cặp chỉ số (5 điểm) ### Tóm tắt đề bài: Cho dãy gồm $n$ số nguyên dương $a_1, a_2, \dots, a_n$. **Yêu cầu:** Hỏi có tất cả bao nhiêu **cặp chỉ số** ($i, j$) khác nhau thỏa mãn tất cả các điều kiện dưới đây: - $1 \le i \le j \le n$. - $a_i + a_j$ là một số lẻ chia hết cho $3$. **Dữ liệu đảm bảo:** - $1 \le n \le 10^6$. - $1 \le a_i \le 10^9$. **Subtasks:** - $50\%$ số điểm tương ứng với $1 \le n \le 10^4$. - $50\%$ số điểm không có ràng buộc gì thêm. ### Subtask 1 Duyệt hai vòng lặp để ==xét mọi cặp chỉ số== và đếm số cặp thỏa mãn bài toán. **Độ phức tạp thời gian:** $O \left( n^2 \right)$. ### Subtask 2 Xét trường hợp ta cố định $A_i$, khi đó cần đếm số lượng $j$ thỏa: - $j \le i$. - $(A_j + A_i) \bmod 3 = 0$, hay $A_j \bmod 3 + A_i \bmod 3 = 0$. - $A_j + A_i$ lẻ, hay ==đúng một trong hai== số là lẻ. Điều này có thể thực hiện bằng cách sử dụng mảng đếm như sau: - Lưu $\text{even}_i$ là ==số lượng số lẻ chia cho $3$ dư $i$== $(0 \le i \lt 3)$. - Lưu $\text{odd}_i$ là ==số lượng số chẵn chia cho $3$ dư $i$== $(0 \le i \lt 3)$. Như vậy, ta duyệt qua mảng $A$ và thực hiện: - Nếu $A_i$ lẻ, có thể ghép với các số $A_j$ chẵn mà $A_j \bmod 3 + A_i \bmod 3 = 0$. - Nếu $A_i$ chẵn, có thể ghép với các số $A_j$ lẻ mà $A_j \bmod 3 + A_i \bmod 3 = 0$. **Độ phức tạp thời gian:** $O \left( n \log n \right)$. :::success :::spoiler Code ```cpp=1 #include <bits/stdc++.h> using namespace std; const int N = 1e6; int n, res, odd[3], even[3]; int main() { cin >> n; while (n--) { int x; cin >> x; if (x & 1) { res += even[(3 - x % 3) % 3]; odd[x % 3]++; } else { res += odd[(3 - x % 3) % 3]; even[x % 3]++; } } cout << res; return 0; } ``` ::: ## Bài 4: Chọn số (5 điểm) ### Tóm tắt đề bài: Cho bảng số nguyên có $2$ hàng và $n$ cột. Ô giao hàng $i$ và cột $j$ gọi là ô $(i, j)$ chứa số nguyên $a_{i,j}$ và **bộ quy tắc** chọn các số trên bảng như sau: - Mỗi cột bắt buộc chọn đúng **một số duy nhất**. - Trên cùng một hàng chọn không quá $2$ số liên tiếp nhau. **Yêu cầu:** Cho biết **tổng giá trị lớn nhất của tất cả các số được chọn** có trong bảng thỏa mãn **bộ quy tắc**. **Dữ liệu đảm bảo:** - $1 \le n \le 10^6$. - $|a_{i, j}| \le 10^6$. **Subtasks:** - $30\%$ số điểm tương ứng với $1 \le n \le 20$. - $70\%$ số điểm không có ràng buộc gì thêm. ### Subtask 1 Áp dụng giải thuật ==quay lui== để thử ==mọi cách== xếp bảng thỏa mãn quy tắc, sau đó lấy tổng giá trị lớn nhất. **Độ phức tạp thời gian:** $O \left( 2^n \right)$ ### Subtask 2 - **Định nghĩa:** - ==$dp_{1, j}$== là tổng lớn nhất tạo được xét $j$ cột đầu tiên và lấy ô $(1, j)$. - ==$dp_{2, j}$== là tổng lớn nhất tạo được xét $j$ cột đầu tiên và lấy ô $(2, j)$. - **Khởi gán:** - ==$dp_{1, 1}$== $= a_{1, 1}$. - ==$dp_{2, 1}$== $= a_{2, 1}$. - **Công thức:** - $dp_{1, j}$ bằng giá trị lớn nhất trong $4$ giá trị sau đây: - $dp_{2, j-1} + a_{1, j}$ (cột $j-1$ lấy ô ở hàng 2, cột $j$ lấy ô ở hàng 1) - $dp_{2, j-2} + a_{1, j} + a_{1, j-1}$ (cột $j-1$ lấy ô ở hàng 1, cột $j$ lấy ô ở hàng 1) - Tương tự với $dp_{2, j}$. - **Kết quả:** ==$dp_K$==. **Độ phức tạp thời gian:** $O \left( n \right)$. :::success :::spoiler Code ```cpp=1 #include <bits/stdc++.h> using namespace std; const int N = 1e6; int n, A[2][N+1], dp[2][N+1]; int main() { cin >> n; for (int i = 0; i <= 1; i++) for (int j = 1; j <= n; j++) cin >> A[i][j]; dp[0][1] = A[0][1]; dp[1][1] = A[1][1]; for (int j = 2; j <= n; j++) { dp[0][j] = max(dp[1][j-1] + A[0][j], dp[1][j-2] + A[0][j] + A[0][j-1]); dp[1][j] = max(dp[0][j-1] + A[1][j], dp[0][j-2] + A[1][j] + A[1][j-1]); } cout << max(dp[0][n], dp[1][n]); return 0; } ``` :::