Hướng dẫn giải của Cặp chỉ số bạn bè (đề HSG 12 Phú Thọ 2024-2025)
Chỉ dùng lời giải này khi không có ý tưởng, và đừng copy-paste code từ lời giải này. Hãy tôn trọng người ra đề và người viết lời giải.
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.
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
Đếm cặp (i, j) với i < j sao cho chữ số đầu của ai và chữ số cuối của aj nguyên tố cùng nhau. Chữ số đầu và chữ số cuối chỉ có 9 giá trị khác 0 nên có thể đếm theo chữ số.
Sub 1: Vét cạn - ~O(n^2)~, dùng khi ~n \le 1000~
Xét từng cặp (i, j) với i < j và kiểm tra ƯCLN. Nếu chỉ nộp sub này: đúng 12/20 test.
Sub 2: Đếm theo chữ số - ~O(9n)~
Duyệt j từ trái sang phải, giữ ~cnt[d]~ là số ai (i < j) có chữ số đầu bằng d. Với mỗi j, cộng cnt[d] với các d nguyên tố cùng nhau với chữ số cuối của aj, rồi mới thêm a_j vào cnt. Bẫy: đáp số lên tới ~10^{11}~, dùng long long. Đúng 20/20 test.
Chương trình hoàn chỉnh
Bài có file vào/ra CAU2.INP và CAU2.OUT nên main dùng freopen đúng tên. Nếu ~n \le 1000~ gọi sub1, còn lại gọi sub2.
#include <bits/stdc++.h>
using namespace std;
int n;
vector<string> a; // giu nguyen dang xau de lay chu so dau va chu so cuoi (a_i <= 10^18)
// Sub 1: vet can O(n^2) - xet tung cap (i, j) voi i < j, kiem tra ucln(chu so dau cua a_i, chu so cuoi cua a_j) = 1.
// Dung khi n <= 1000.
void sub1() {
long long ans = 0;
for (int i = 0; i < n; i++)
for (int j = i + 1; j < n; j++) {
int first = a[i][0] - '0';
int last = a[j].back() - '0';
if (__gcd(first, last) == 1) ans++;
}
cout << ans << "\n";
}
// Sub 2: duyet j tu trai sang phai, cntFirst[d] = so i < j co chu so dau la d.
// Voi moi j, cong cntFirst[d] voi moi d nguyen to cung nhau voi chu so cuoi cua a_j (chi 9 gia tri d). O(9n).
void sub2() {
long long cntFirst[10] = {0};
long long ans = 0;
for (int j = 0; j < n; j++) {
int last = a[j].back() - '0';
for (int d = 1; d <= 9; d++)
if (__gcd(d, last) == 1) ans += cntFirst[d];
cntFirst[a[j][0] - '0']++; // them a_j sau khi xet, de chi tinh cap i < j
}
cout << ans << "\n";
}
int main() {
freopen("CAU2.INP", "r", stdin);
freopen("CAU2.OUT", "w", stdout);
ios::sync_with_stdio(false);
cin.tie(nullptr);
cin >> n;
a.resize(n);
for (auto& x : a) cin >> x;
if (n <= 1000) sub1();
else sub2();
return 0;
}
Bình luận