Challenge: Coprime Conundrum
Subdomeniu: Number Theory (number-theory)
Scor cont: 50.0 / 50
Submission status: Accepted
Submission score: 1.0
Submission ID: 464753486
Limbaj: python3
Link challenge: https://www.hackerrank.com/challenges/arthur-and-coprimes/problem
Cerinta
Arthur defines a function, $f(k)$, to be the number of $(p, q)$ pairs such that:
* $1 \lt p \le q \le k$
* $p$ and $q$ are [coprime](https://en.wikipedia.org/wiki/Coprime_integers).
* $p \cdot q = k$
Given an integer, $n$, help Arthur find and print the result of:
$$\sum_{k = 1}^{n} f(k)$$
Input Format
The first line contains a single integer denoting $n$.
Output Format
Print the result of $\sum_{k = 1}^{n} f(k)$ on a new line.
Constraints
* $ 1 \le n \le 10^9$
**Subtasks**
* $ 1 \le n \le 150$ for $\text{30%}$ of the maximum score.
* $ 1 \le n \le 10^6$ for $\text{60%}$ of the maximum score.
Cod sursa
#!/bin/python3
import math
import sys
def solve(n: int) -> int:
lim = int(math.isqrt(n))
spf = list(range(lim + 1))
for i in range(2, int(math.isqrt(lim)) + 1):
if spf[i] == i:
step = i
start = i * i
for j in range(start, lim + 1, step):
if spf[j] == j:
spf[j] = i
uniq_cache = [[] for _ in range(lim + 1)]
for x in range(2, lim + 1):
v = x
ps = []
while v > 1:
p = spf[v]
ps.append(p)
while v % p == 0:
v //= p
uniq_cache[x] = ps
def coprime_count(m: int, p: int) -> int:
# Count 1 <= q <= m with gcd(q, p) = 1.
if m <= 0:
return 0
ps = uniq_cache[p]
k = len(ps)
ans = 0
for mask in range(1 << k):
d = 1
bits = 0
for i in range(k):
if (mask >> i) & 1:
d *= ps[i]
bits += 1
t = m // d
if bits & 1:
ans -= t
else:
ans += t
return ans
total = 0
for p in range(2, lim + 1):
m = n // p
if m < p:
break
# q in [p..m], gcd(p,q)=1
# gcd(p,p) != 1 for p > 1, so using <=p is safe.
total += coprime_count(m, p) - coprime_count(p, p)
return total
def main():
data = sys.stdin.buffer.read().split()
if not data:
return
n = int(data[0])
print(solve(n))
if __name__ == '__main__':
main()
HackerRank Number Theory – Coprime Conundrum
