CF 102282B - Ещё одна
We need to count the positive integers from 1 through r that are coprime with n. Two numbers are coprime when their greatest common divisor is exactly 1. The input contains two integers, n and r, each at most 10^9.
CF 102282B - \u0415\u0449\u0451 \u043e\u0434\u043d\u0430
Rating: -
Tags: -
Solve time: 1m 16s
Verified: yes
Solution
Problem Understanding
We need to count the positive integers from 1 through r that are coprime with n. Two numbers are coprime when their greatest common divisor is exactly 1.
The input contains two integers, n and r, each at most 10^9. The value of r is large enough that checking every number individually is not viable. Even if one greatest-common-divisor computation were very cheap, iterating through all 10^9 candidates would require up to 10^9 gcd computations. The factorization of n is much more promising because n <= 10^9, so trial division only needs to consider divisors up to sqrt(n) <= 31623. Once the distinct prime factors of n are known, there can be at most nine of them, because the product of the first ten primes already exceeds 10^9.
The main edge case is n = 1. Every positive integer is coprime with 1, so for 1 5 the answer is 5. A formula that blindly assumes that n has at least one prime factor could accidentally return zero or leave its initial answer unchanged incorrectly.
The boundary r must be inclusive. For n = 2, r = 2, the numbers under consideration are 1 and 2, and only 1 is coprime with 2, so the answer is 1. A loop over range(1, r) would accidentally exclude r and happen to give the wrong result for many inputs.
Repeated prime factors must also be handled correctly. For n = 12, r = 12, the relevant prime factors are only 2 and 3, not 2, 2, 3. The answer is 4, corresponding to 1, 5, 7, 11. Treating repeated factors as separate inclusion-exclusion choices would count the same forbidden condition multiple times.
A final boundary case is when n itself is much larger than r. For n = 7, r = 3, all three numbers 1, 2, 3 are coprime with 7, so the answer is 3. There is no reason to restrict the candidates according to the size of n; only their common divisors matter.
Approaches
The direct solution is to inspect every integer x from 1 through r and test whether gcd(x, n) = 1. This is correct because the definition of the required set is exactly that gcd condition. However, with r = 10^9, the algorithm may perform 10^9 gcd computations. Even though Euclid's algorithm itself is fast, a billion iterations is far beyond the intended time budget.
The useful observation is that whether x is coprime with n depends only on the distinct prime factors of n. Suppose those primes are p1, p2, ..., pk. An integer fails to be coprime with n exactly when it is divisible by at least one of these primes.
We can count the integers that are divisible by at least one forbidden prime using inclusion-exclusion. For every nonempty subset of the distinct prime factors, let d be the product of the primes in that subset. The numbers divisible by every prime in the subset are exactly the multiples of d, so there are r // d of them among 1 through r.
For subsets containing an odd number of primes, these multiples are added. For subsets containing an even number of primes, they are subtracted. If bad is the resulting count, the desired answer is r - bad.
The only remaining task is finding the distinct prime factors of n. Trial division up to the square root is sufficient for n <= 10^9. After extracting every occurrence of a prime factor, we keep that prime only once, because inclusion-exclusion needs distinct divisibility conditions.
There is also a useful equivalent interpretation through Euler's totient function. If the upper bound were exactly n, the answer would be phi(n). Here the interval ends at arbitrary r, so the usual closed-form formula for phi(n) is not enough. Inclusion-exclusion applies directly to an arbitrary r.
| Approach | Time Complexity | Space Complexity | Verdict |
|---|---|---|---|
| Brute Force | O(r log n) |
O(1) |
Too slow |
| Optimal | O(sqrt(n) + 2^k) |
O(k) |
Accepted |
Here k is the number of distinct prime factors of n. Since n <= 10^9, k <= 9, so the subset enumeration has at most 512 cases.
Algorithm Walkthrough
- Factorize
nby trying divisors from2throughsqrt(n). Whenever a divisorpdivides the current value ofn, recordponce and repeatedly divide it out. Removing all copies is necessary because only the presence of the prime matters for coprimality. - After trial division, if the remaining value is greater than
1, record it as another prime factor. A remaining value greater than1cannot have a smaller unprocessed factor, so it must itself be prime. - Enumerate every subset of the distinct prime factors. For a subset, multiply its selected primes to obtain
d. The integers divisible by every selected prime are precisely the multiples ofd, givingr // dsuch integers. - Add
r // dwhen the subset contains an odd number of primes and subtract it when the subset contains an even number of primes. This is the inclusion-exclusion correction for overlaps between divisibility conditions. - Subtract the number of non-coprime integers from
r. The remaining count is exactly the number of integers in[1, r]whose gcd withnequals1.
Why it works
Let P be the set of distinct prime factors of n. An integer x is not coprime with n exactly when at least one prime in P divides x. Thus the unwanted integers form the union of the sets A_p = {x : p divides x} for p in P.
For any subset of these primes with product d, its intersection contains exactly the multiples of d, and there are r // d such integers up to r. Inclusion-exclusion counts the union exactly by alternating addition and subtraction according to subset size. Consequently, bad is precisely the number of integers sharing a nontrivial divisor with n, and r - bad counts exactly the coprime integers.
The factorization stage supplies every prime in P exactly once, so the inclusion-exclusion stage represents every possible common prime divisor and no irrelevant condition.
Python Solution
import sys
input = sys.stdin.readline
def solve():
n, r = map(int, input().split())
x = n
primes = []
p = 2
while p * p <= x:
if x % p == 0:
primes.append(p)
while x % p == 0:
x //= p
p += 1 if p == 2 else 2
if x > 1:
primes.append(x)
k = len(primes)
bad = 0
for mask in range(1, 1 << k):
product = 1
bits = 0
for i in range(k):
if mask & (1 << i):
product *= primes[i]
bits += 1
count = r // product
if bits % 2 == 1:
bad += count
else:
bad -= count
print(r - bad)
if __name__ == "__main__":
solve()
The code first copies n into x, because trial division repeatedly reduces the number being factored. The list primes contains each distinct prime factor exactly once.
The loop starts with p = 2, then checks only odd values after 2. This avoids testing even divisors that cannot be prime. The condition p * p <= x is safe because if x has a composite factorization, one of its factors is at most its square root. When the loop ends, a remaining x > 1 must be prime.
The subset loop uses a bitmask. Bit i determines whether primes[i] belongs to the current subset. product becomes the product of the selected primes, while bits records the subset size and determines the inclusion-exclusion sign.
The calculation uses integer division r // product, not (r - 1) // product, because r itself belongs to the interval. Python integers also remove any concern about overflow, although all intermediate products here are small enough for ordinary 64-bit integers as well.
For n = 1, the factor list remains empty. The subset loop has no iterations, so bad = 0 and the answer becomes r, which is exactly correct.
Worked Examples
For the first sample, n = 2 has one distinct prime factor, 2.
| Mask | Selected primes | Product | Subset size | r // product |
bad |
|---|---|---|---|---|---|
1 |
{2} |
2 |
1 |
1 |
1 |
The only bad number up to 2 is 2 itself. Subtracting it from the two candidates gives 2 - 1 = 1, so the output is 1.
For the second sample, n = 10 has distinct prime factors 2 and 5.
| Mask | Selected primes | Product | Subset size | r // product |
bad |
|---|---|---|---|---|---|
01 |
{2} |
2 |
1 |
4 |
4 |
10 |
{5} |
5 |
1 |
1 |
5 |
11 |
{2, 5} |
10 |
2 |
0 |
5 |
Among 1 through 9, four numbers are divisible by 2, one is divisible by 5, and their intersection contains no number. Thus five numbers are not coprime with 10, leaving 9 - 5 = 4. The coprime numbers are 1, 3, 7, 9, which also demonstrates why being prime is unrelated to the required property.
Complexity Analysis
| Measure | Complexity | Explanation |
|---|---|---|
| Time | O(sqrt(n) + 2^k k) |
Trial division takes O(sqrt(n)), and each of the 2^k subsets checks at most k primes |
| Space | O(k) |
Only the distinct prime factors and a constant number of variables are stored |
For n <= 10^9, sqrt(n) <= 31623, so the factorization requires only a small number of trial divisions. Also, k <= 9, making the subset enumeration tiny. The algorithm therefore avoids any dependence on the potentially billion-sized value of r and comfortably fits the given limits.
Test Cases
import sys
import io
def solve_data(inp: str) -> str:
old_stdin = sys.stdin
old_stdout = sys.stdout
sys.stdin = io.StringIO(inp)
sys.stdout = io.StringIO()
try:
n, r = map(int, sys.stdin.readline().split())
x = n
primes = []
p = 2
while p * p <= x:
if x % p == 0:
primes.append(p)
while x % p == 0:
x //= p
p += 1 if p == 2 else 2
if x > 1:
primes.append(x)
k = len(primes)
bad = 0
for mask in range(1, 1 << k):
product = 1
bits = 0
for i in range(k):
if mask & (1 << i):
product *= primes[i]
bits += 1
count = r // product
if bits & 1:
bad += count
else:
bad -= count
print(r - bad)
return sys.stdout.getvalue().strip()
finally:
sys.stdin = old_stdin
sys.stdout = old_stdout
# Provided samples
assert solve_data("2 2\n") == "1", "sample 1"
assert solve_data("10 9\n") == "4", "sample 2"
# Minimum-size input: the only positive integer is coprime with itself when it is 1.
assert solve_data("1 1\n") == "1", "minimum input"
# n = 1 means every number up to r is coprime with n.
assert solve_data("1 1000000000\n") == "1000000000", "n = 1"
# Equal values with repeated prime factors: gcd(1, 10)=1, gcd(3,10)=1,
# gcd(7,10)=1, gcd(9,10)=1.
assert solve_data("10 10\n") == "4", "equal values"
# Boundary where r itself is divisible by n's prime factor.
assert solve_data("2 2\n") == "1", "inclusive upper boundary"
# Large composite n with repeated factors: 1e9 = 2^9 * 5^9.
# Count = 1e9 * (1 - 1/2) * (1 - 1/5) = 400000000.
assert solve_data("1000000000 1000000000\n") == "400000000", "maximum-size case"
| Test input | Expected output | What it validates |
|---|---|---|
1 1 |
1 |
Minimum input and the empty prime-factor set |
1 1000000000 |
1000000000 |
Every candidate is coprime with 1 |
10 10 |
4 |
Equal n and r, with multiple distinct prime factors |
2 2 |
1 |
Inclusive upper boundary |
1000000000 1000000000 |
400000000 |
Maximum-size values and repeated prime factors |
Edge Cases
For n = 1, r = 5, the factorization produces an empty list because 1 has no prime factors. There are no inclusion-exclusion subsets, so bad remains zero. The final calculation is 5 - 0 = 5, correctly counting every number from 1 to 5.
For n = 2, r = 2, the factor list is [2]. The single subset represents numbers divisible by 2, and 2 // 2 = 1. Thus one candidate is rejected and the answer is 2 - 1 = 1. This confirms that the upper endpoint r is included.
For n = 12, r = 12, factorization produces [2, 3], not [2, 2, 3]. Inclusion-exclusion counts 6 multiples of 2, 4 multiples of 3, and subtracts 2 multiples of 6. Hence bad = 6 + 4 - 2 = 8, giving 12 - 8 = 4. The four valid values are 1, 5, 7, 11.
For n = 7, r = 3, factorization produces [7], but 3 // 7 = 0. No number up to 3 is divisible by 7, so bad = 0 and the answer is 3. This shows why the method works even when every candidate is smaller than n.
For the maximum-size case n = r = 10^9, the distinct factors are 2 and 5. The bad count is 500000000 + 200000000 - 100000000 = 600000000, leaving 400000000 valid numbers. The algorithm reaches this result without iterating over any of the 10^9 candidate integers.