-
Notifications
You must be signed in to change notification settings - Fork 1.6k
/
sorted-gcd-pair-queries.cpp
33 lines (32 loc) · 1.1 KB
/
sorted-gcd-pair-queries.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
// Time: O(rlogr + qlogr), r = max(nums)
// Space: O(r)
// number theory, freq table, prefix sum, binary search
class Solution {
public:
vector<int> gcdValues(vector<int>& nums, vector<long long>& queries) {
unordered_map<int, int> cnt1;
for (const auto& x : nums) {
++cnt1[x];
}
vector<int64_t> cnt2(ranges::max(nums) + 1);
for (int g = size(cnt2) - 1; g >= 1; --g) {
int64_t c = 0;
for (int ng = g; ng < size(cnt2); ng += g) {
c += cnt1[ng];
}
cnt2[g] = c * (c - 1) / 2;
for (int ng = g + g; ng < size(cnt2); ng += g) {
cnt2[g] -= cnt2[ng];
}
}
vector<int64_t> prefix(size(cnt2) + 1);
for (int i = 0; i < size(prefix) - 1; ++i) {
prefix[i + 1] += prefix[i] + cnt2[i];
}
vector<int> result(size(queries));
for (int i = 0; i < size(queries); ++i) {
result[i] = distance(cbegin(prefix), upper_bound(cbegin(prefix), cend(prefix), queries[i])) - 1;
}
return result;
}
};