Краткий ответ
Пусть:
- \(S_k\) — число пар нажатий с одинаковыми номерами клавиш;
- \(S_c\) — число пар с одинаковыми кодами;
- \(G\) — число пар с одновременно одинаковыми номерами и кодами.
Тогда:
\[ B=S_k-G, \qquad N=S_c-G, \]
\[ P=\binom{n}{2}-S_k-S_c+G. \]
После этого вычисляем
\[ \frac{\sqrt G+\sqrt P}{\sqrt B+\sqrt N}. \]
Если \(B=N=0\), выводим \(-1\).
Почему это работает
Для группы из \(t\) одинаковых значений число пар внутри неё равно:
\[ \binom{t}{2}=\frac{t(t-1)}2. \]
Поэтому:
- сортируем номера \(k_i\) и считаем пары одинаковых номеров;
- сортируем коды \(c_i\) и считаем пары одинаковых кодов;
- сортируем пары \((k_i,c_i)\) и считаем хорошие пары \(G\).
Почти хорошие пары — это пары, у которых различаются и номера, и коды. Из всех пар исключаем пары с одинаковым номером или одинаковым кодом:
\[ P=\binom{n}{2}-(G+B)-(G+N)+G =\binom{n}{2}-S_k-S_c+G. \]
Решение на C++17
#include <bits/stdc++.h>
using namespace std;
long long countEqualPairs(vector<long long> values) {
sort(values.begin(), values.end());
long long result = 0;
int n = static_cast<int>(values.size());
for (int i = 0; i < n; ) {
int j = i + 1;
while (j < n && values[j] == values[i]) {
++j;
}
long long cnt = j - i;
result += cnt * (cnt - 1) / 2;
i = j;
}
return result;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;
cin >> n;
vector<long long> k(n), c(n);
for (long long &x : k) {
cin >> x;
}
for (long long &x : c) {
cin >> x;
}
long long sameK = countEqualPairs(k);
long long sameC = countEqualPairs(c);
vector<pair<long long, long long>> both(n);
for (int i = 0; i < n; ++i) {
both[i] = {k[i], c[i]};
}
sort(both.begin(), both.end());
long long good = 0;
for (int i = 0; i < n; ) {
int j = i + 1;
while (j < n && both[j] == both[i]) {
++j;
}
long long cnt = j - i;
good += cnt * (cnt - 1) / 2;
i = j;
}
long long totalPairs = 1LL * n * (n - 1) / 2;
long long bad = sameK - good;
long long almostBad = sameC - good;
long long almostGood = totalPairs - sameK - sameC + good;
if (bad == 0 && almostBad == 0) {
cout << -1 << '\n';
return 0;
}
long double numerator =
sqrtl(static_cast<long double>(good)) +
sqrtl(static_cast<long double>(almostGood));
long double denominator =
sqrtl(static_cast<long double>(bad)) +
sqrtl(static_cast<long double>(almostBad));
long double answer = numerator / denominator;
cout << fixed << setprecision(15) << answer << '\n';
return 0;
}
Сложность решения:
\[ O(n\log n) \]
по времени и \(O(n)\) по памяти.