**Lời giải đề thi chuyên Tin PTNK 2025-2026**
---
Tác giả: Hồ Bảo Phúc
> [!Note]
> Thông tin liên hệ tác giả: [**Hồ Bảo Phúc**](https://www.facebook.com/ho.bao.phuc.42906/)
---
> [!Warning]
> Lời giải chỉ mang tính chất tham khảo, không phải là lời giải chính thức.
> Các bạn có thể xem đề [**tại đây**](https://drive.google.com/drive/folders/1L55emJfISRcbxutPPdmF2hc8bH9Wr7Nm)
---
**Bài 1**
---
**Lời giải**
Đây là 1 bài kỹ thuật lập trình cơ bản, ta chỉ cần kiểm tra xem $a[i] == a[i - 1]$ và $a[i]$ == "ONLINE" thì ta cập nhật biến đếm và kết quả.
<details>
<summary><strong>Code</strong></summary>
```cpp
/*
author: hbphuc2009
from: High School for the Gifted, VNU-HCM
*/
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define nmax 100005
#define MOD 1000000007
#define endl '\n'
int n;
string a[nmax];
bool flag = false;
void input(){
cin >> n;
for(int i = 1; i <= n; i++){
cin >> a[i];
if(a[i] == "ONLINE") flag = true;
}
}
void solve(){
if(flag == false){
cout << 0;
return;
}
int ans = 0;
int d = 0;
if(a[1] == "ONLINE") d ++, ans = 1;
for(int i = 2; i <= n; i++){
if(a[i] == a[i - 1]){
d ++;
}
else{
if(a[i - 1] == "ONLINE") ans = max(ans, d);
d = 1;
}
}
if(a[n] == "ONLINE") ans = max(ans, d);
cout << ans;
}
int main(){
cin.tie(0) -> sync_with_stdio(0);
freopen("STREAK.INP", "r", stdin);
freopen("STREAK.OUT", "w", stdout);
input();
solve();
}
```
</details>
---
**Bài 2**
---
**Lời giải**
**Sort** lại các trạm sạc theo thứ tự tăng dần, nếu khoảng cách giữa 2 trạm sạc liền kề nhau (và khoảng cách giữa điểm đầu và trạm sạc 1, điểm đến và trạm sạc cuối) lớn hơn *p*, thì in ra -1.
Nếu $n = 0$ và *p* < $D$, in ra -1.
Duy trì biến *cur* là toạ độ của chiếc xe điện, ta chặt nhị phân xem có trạm sạc nào có toạ độ lớn hơn hoặc bằng *cur* + *p* hay ko, nếu bằng thì cập nhật *cur* tại trạm sạc đó, nếu lớn hơn thì cập nhật *cur* ở trạm sạc ngay trước đó và tăng biến đếm.
<details>
<summary><strong>Code</strong></summary>
```cpp
/*
author: hbphuc2009
from: High School for the Gifted, VNU-HCM
*/
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define nmax 1005
#define MOD 1000000007
#define endl '\n'
int n, p, target;
int a[nmax];
void input(){
cin >> n >> p >> target;
for(int i = 1; i <= n; i++){
cin >> a[i];
}
}
void solve(){
sort(a + 1, a + n + 1);
if((p < target - a[n]) or (n == 0 and p < target)){
cout << -1 << endl;
return;
}
for(int i = 1; i <= n; i++){
if(a[i] - a[i - 1] > p){
cout << -1 << endl;
return;
}
}
int sum = 0;
int ans = 0;
while(sum < target){
if(sum + p >= target){
break;
}
int k = lower_bound(a + 1, a + n + 1, sum + p) - a;
if(a[k] == p){
ans ++;
sum = a[k];
}
else{
ans ++;
sum = a[k - 1];
}
}
cout << ans << endl;
}
int main(){
cin.tie(0) -> sync_with_stdio(0);
freopen("EVTRIP.INP", "r", stdin);
freopen("EVTRIP.OUT", "w", stdout);
input();
solve();
}
```
</details>
---
**Bài 3**
---
**Lời giải**
Gọi `dp[i][j]` là số lần xoá ít nhất để xâu $s_i$ -> $s_j$ là xâu palindrome. Output là `dp[1][n]`
- `dp[i][j] = dp[i + 1][j - 1]` với `s[i] = s[j]`
- `dp[i][j] = max(dp[i + 1][j], dp[i][j - 1]) + 1` với `s[i] != s[j]`
**Cơ sở**: `dp[i][i] = 0` , $1 <= i <= n$
<details>
<summary><strong>Code</strong></summary>
```cpp
/*
author: hbphuc2009
from: High School for the Gifted, VNU-HCM
*/
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define nmax 2005
#define MOD 1000000007
#define endl '\n'
int n;
string s;
int dp[nmax][nmax];
void input(){
getline(cin, s);
n = s.size();
s = " " + s;
}
void solve(){
for(int i = 1; i <= n; i++) dp[i][i] = 0;
for(int i = n - 1; i >= 1; i--){
for(int j = i + 1; j <= n; j++){
if(s[i] == s[j]){
dp[i][j] = dp[i + 1][j - 1];
}
else{
dp[i][j] = min(dp[i + 1][j], dp[i][j - 1]) + 1;
}
}
}
cout << dp[1][n];
}
int main(){
cin.tie(0) -> sync_with_stdio(0);
freopen("WORDGAME.INP", "r", stdin);
freopen("WORDGAME.OUT", "w", stdout);
input();
solve();
}
```
</details>