Lời Giải HSG Tin TP Hà Nội - 2023
Bài 1. Số chính phương đặc biệt
Số chính phương đặc biệt là số chính phương được tạo bởi một số nguyên tố.
Ví dụ: nên và là số chính phương đặc biệt còn thì không phải là số chính phương đặc biệt.
Yêu cầu
Cho 2 số nguyên dương . Hãy đếm xem trong đoạn có bao nhiêu số chính phương đặc biệt?
Dữ liệu
Vào từ tệp văn bản CP.INP: gồm hai số nguyên dương .
Kết quả
Ghi ra tệp văn bản CP.OUT: gồm một dòng chứa một số duy nhất là kết quả của bài toán.
Ràng buộc
- Có 80% số test ứng với 80% số điểm của bài thoả mãn .
- 20% số test còn lại ứng với 20% số điểm của bài không có ràng buộc gì thêm.
Ví dụ
| CP.INP | CP.OUT |
|---|---|
| 2 10 | 2 |
Lời giải
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int main()
{
ll a, b;
cin >> a >> b;
int n = 1e6;
vector<bool> sieve(n + 1, true);
for (int i = 2; i <= sqrt(n); i++)
{
if (sieve[i])
{
for (int j = i * i; j <= n; j += i)
sieve[j] = false;
}
}
ll ans = 0;
for (ll i = sqrt(a); i * i <= b; i++)
{
ll ii = i * i;
if (sieve[i] && a <= ii && ii <= b)
ans++;
}
cout << ans;
return 0;
}Bài 2. Bảng số
Cho một bảng vuông gồm hàng và cột. Các hàng được đánh số từ 1 đến , các cột được đánh số từ 1 đến . Ở ô hàng thứ và cột thứ có giá trị là .
Yêu cầu
Cho một số nguyên dương . Hãy đếm số lượng ô trong bảng có giá trị bằng .
Dữ liệu
Vào từ tệp văn bản BS.INP: gồm hai số nguyên và là kích thước của bảng và số nguyên cần đếm trong bảng.
Kết quả
Ghi ra tệp văn bản BS.OUT: số nguyên duy nhất là số lượng ô trong bảng có giá trị bằng .
Ràng buộc
- Có 70% số test ứng với 70% số điểm của bài thoả mãn .
- 30% số test còn lại ứng với 30% số điểm của bài không có ràng buộc gì thêm.
Ví dụ
| BS.INP | BS.OUT |
|---|---|
| 6 5 | 2 |
| 6 12 | 4 |
| 5 13 | 0 |
Giải thích:
| 1 | 2 | 3 | 4 | 5 | 6 |
|---|---|---|---|---|---|
| 2 | 4 | 6 | 8 | 10 | 12 |
| 3 | 6 | 9 | 12 | 15 | 18 |
| 4 | 8 | 12 | 16 | 20 | 24 |
| 5 | 10 | 15 | 20 | 25 | 30 |
| 6 | 12 | 18 | 24 | 30 | 36 |
Lời giải
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int main()
{
ll n, x, ans = 0;
cin >> n >> x;
for (int i = 1; i <= n; i++)
{
if (x % i != 0 || x < i)
continue;
if (x / i <= n)
ans++;
}
cout << ans;
return 0;
}Bài 3. Chia tiền thưởng
Nhờ hoàn thành tốt công việc, An và Bình được công ty thưởng tờ tiền.
Tờ tiền thứ có mệnh giá . Hai bạn muốn chia đôi số tiền thành hai phần bằng nhau bằng cách chia cho mỗi người một số tờ tiền. Vì thế hai bạn quyết định sẽ chọn ra những tờ tiền để tổng số tiền hai bạn nhận được bằng nhau và lớn nhất, phần còn lại (nếu có) sẽ đem đi đầu tư.
Yêu cầu
Hãy giúp hai bạn tìm tổng số tiền lớn nhất mà mỗi người nhận được trước khi đầu tư.
Dữ liệu
Vào từ tệp văn bản CT.INP:
- Dòng đầu tiên chứa số nguyên dương .
- Dòng thứ hai bao gồm số nguyên dương là mệnh giá của những tờ tiền. Tổng giá trị những tờ tiền sẽ không vượt quá .
Kết quả
Ghi ra tệp văn bản CT.OUT: gồm một dòng duy nhất là số tiền lớn nhất mà mỗi người nhận được.
Ràng buộc
- Có 40% số test ứng với 40% số điểm của bài thoả mãn .
- 30% số test tiếp theo ứng với 30% số điểm của bài thoả mãn .
- 30% số test còn lại ứng với 30% số điểm của bài không có ràng buộc gì thêm.
Ví dụ
| CT.INP | CT.OUT | Giải thích |
|---|---|---|
| 5 1 2 4 5 2 | 7 | An có thể chọn những tờ tiền có mệnh giá 1, 2, 4. Bình sẽ chọn tờ tiền có mệnh giá 5, 2. Mỗi người sẽ nhận được tổng số tiền là 7. Không còn tiền để đi đầu tư. |
| 5 9 8 4 5 13 | 17 | An sẽ chọn những tờ tiền có mệnh giá 9, 8. Bình sẽ chọn tờ tiền có mệnh giá 4, 13. Mỗi người sẽ nhận được tổng số tiền là 17. Tờ tiền có mệnh giá 5 sẽ đem đi đầu tư. |
Lời giải
Ý tưởng
Mục tiêu của ta là tìm ra số tiền lớn nhất mà mỗi người có được sau khi chia tiền với tiêu chí là 2 người đều có số tiền như nhau, nghĩa là số tiền còn lại mang đi đầu tư là nhỏ nhất và số tiền chênh lệch giữa họ là bằng 0.
Ý tưởng là ta sẽ bắt đầu tính toán khi số tiền chênh lệch giữa 2 người là lớn nhất, và lần lượt giảm số tiền chênh lệch đó đi đến khi bằng 0.
Gọi:
- là số tiền chênh lệch giữa 2 người.
- là giá trị tờ tiền thứ .
Tại vị trí , khi mà số tiền chênh lệch giữa 2 người là , và công ty mới chỉ thưởng cho 2 người đến tờ tiền thứ , thì ta quan tâm việc mỗi người được nhiều nhất bao nhiêu tiền sau khi chia. Nói cách khác, số tiền để lại mang đi đầu tư nhỏ nhất là bao nhiêu.
Ta định nghĩa là số tiền nhỏ nhất để lại.
Hiển nhiên rằng, số tiền chênh lệch giữa 2 người không thể lớn hơn tổng số tiền mà công ty đã thưởng. Vì vậy ta cần thêm một giá trị nữa, , tổng số tiền từ tờ thứ đến .
Khi xét đến tờ thứ tại số tiền chênh lệch :
Nếu (số tiền chênh lệch lớn hơn cả tổng số tiền công ty thưởng), vậy thì sự chênh lệch đó không tồn tại:
Nếu (số tiền chênh lệch bằng tổng số tiền công ty thưởng), vậy thì một người sẽ không có số tiền nào và người kia sẽ có toàn bộ số tiền:
Trường hợp còn lại:
Hai người quyết định để lại tờ tiền thứ để đầu tư:
Ngược lại, ta lại có 2 lựa chọn:
Tờ tiền thứ thuộc về người đang có ít tiền hơn:
Tờ tiền thứ thuộc về người đang có nhiều tiền hơn, và tất nhiên số tiền chênh lệch sau đó vẫn không thể vượt quá được tổng số tiền tính đến tờ thứ :
⇒ Vậy giá trị tốt ưu nhất là giá trị nhỏ nhất trong 3 giá trị trên.
Kết quả của bài toán chính là tổng số tiền trừ đi và chia cho 2.
Code
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define nl '\n'
#define inf 1e18
int main()
{
int n;
cin >> n;
vector<ll> m(n), p(n);
for (int i = 0; i < n; i++)
{
cin >> m[i];
p[i] = (i == 0 ? m[i] : p[i - 1] + m[i]);
}
vector<vector<ll>> dp(n, vector<ll>(p[n - 1] + 1));
fill(dp[0].begin(), dp[0].end(), inf);
dp[0][0] = m[0];
dp[0][m[0]] = 0;
for (int i = 1; i < n; i++)
{
for (int j = p[n - 1]; j >= 0; j--)
{
if (j > p[i])
dp[i][j] = inf;
else if (j == p[i])
dp[i][j] = 0;
else
{
dp[i][j] = min(dp[i - 1][j] + m[i], dp[i - 1][abs(j - m[i])]);
if (j + m[i] <= p[i])
dp[i][j] = min(dp[i][j], dp[i - 1][j + m[i]]);
}
}
}
p[n - 1] = (p[n - 1] - dp[n - 1][0]) / 2;
cout << p[n - 1];
return 0;
}Bài 4. Trạm gác trung tâm
Ban quản lý rừng nguyên sinh đang quản lý một khu vực rộng lớn.
Họ đã xây dựng trạm canh gác rừng (được đánh số từ ) và các trạm này được nối với nhau bởi con đường.
Trong trạm canh gác người ta đã chọn ra trạm làm trạm gác trung tâm - nơi điều hành các trạm gác nhỏ hơn và chứa các dụng cụ, phương tiện bảo vệ rừng.
Để đi lại và vận chuyển thiết bị dễ dàng giữa các trạm gác trung tâm, Ban quản lí quyết định nâng cấp một số con đường sao cho trạm gác trung tâm đều đi được đến nhau.
Yêu cầu
Hãy chọn các con đường nối trạm gác trung tâm để nâng cấp sao cho tổng độ dài của các con đường này là nhỏ nhất.
Dữ liệu
Vào từ tệp văn bản TG.INP:
- Dòng đầu tiên ghi ba số nguyên dương lần lượt là số lượng các trạm gác, số lượng con đường nối giữa các trạm gác và số lượng các trạm gác trung tâm .
- Dòng thứ hai ghi số nguyên là số hiệu của trạm gác trung tâm.
- Trong dòng tiếp theo, mỗi dòng ghi ba số nguyên với ý nghĩa con đường hai chiều nối trực tiếp giữa hai trạm và có độ dài là .
Kết quả
Ghi ra tệp văn bản TG.OUT: một dòng duy nhất chứa tổng độ dài các con đường thỏa mãn yêu cầu trên.
Ràng buộc
- Có 40% số test ứng với 40% số điểm của bài thoả mãn .
- 30% số test tiếp theo ứng với 30% số điểm của bài thoả mãn .
- 30% số test còn lại ứng với 30% số điểm của bài không có ràng buộc gì thêm.
Ví dụ
| TG.INP | TG.OUT | Giải thích |
|---|---|---|
| 5 3 8 1 3 5 1 2 2 1 3 10 1 4 12 2 4 5 2 5 7 3 4 2 3 5 10 4 5 6 | 15 | Cần làm các con đường: 1 2 2 4 3 4 4 5 Tổng độ dài nhỏ nhất là: 15 |
Bài 5. Sắp xếp hoán vị
Cho số nguyên dương và dãy hoán vị từ đến .
Hãy tính tổng chi phí nhỏ nhất để sắp xếp lại dãy con này thành dãy tăng dần.
Biết rằng có thể chọn một dãy con liên tiếp từ đến và sắp xếp lại dãy con này thành dãy tăng dần với chi phí là (lấy phần nguyên, ví dụ ).
Dữ liệu
Vào từ tệp văn bản SX.INP:
- Dòng đầu tiên chứa số nguyên dương .
- Dòng thứ hai chứa số nguyên dương là hoán vị từ đến .
Kết quả
Ghi ra tệp văn bản SX.OUT: chỉ phí nhỏ nhất để sắp xếp dãy hoán vị đã cho thành dãy tăng dần.
Ràng buộc
- Có 30% số test ứng với 30% số điểm của bài thoả mãn .
- 30% số test tiếp theo ứng với 30% số điểm của bài thoả mãn .
- 30% số test tiếp theo ứng với 30% số điểm của bài thoả mãn .
- 10% số test còn lại ứng với 10% số điểm của bài thoả mãn .
Ví dụ
| SX.INP | SX.OUT | Giải thích |
|---|---|---|
| 5 3 1 4 2 5 | 2 | Chọn dãy con [3, 1] mất chi phí 1 và chuyển thành [1, 3, 4, 2, 5], sau đó chọn dãy con [3, 4, 2] với chi phí 1 để sắp xếp thành dãy [1, 2, 3, 4, 5] với tổng chi phí là 2. |