CF 109B - Lucky Probability
We are asked to calculate the probability that if Petya and Vasya each pick an integer randomly from their respective intervals, the interval between the two chosen numbers contains exactly k lucky numbers. Lucky numbers are those containing only the digits 4 and 7.
Rating: 1900
Tags: brute force, probabilities
Solve time: 2m 23s
Verified: yes
Solution
Problem Understanding
We are asked to calculate the probability that if Petya and Vasya each pick an integer randomly from their respective intervals, the interval between the two chosen numbers contains exactly k lucky numbers. Lucky numbers are those containing only the digits 4 and 7. The input provides the bounds of the intervals for both players (pl to pr for Petya, vl to vr for Vasya) and the target count k of lucky numbers. The output is the probability as a floating-point number.
The constraints give upper bounds of $10^9$ for the intervals and k can go up to 1000. This immediately rules out any approach that iterates over all integers in the intervals directly, because the total number of pairs can be up to $(10^9)^2 = 10^{18}$, which is computationally impossible. The problem demands an approach that leverages the small number of lucky numbers compared to the potentially huge interval size.
A naive implementation might attempt to enumerate every integer in both intervals, count lucky numbers in each resulting subinterval, and then divide by the total number of pairs. This would fail for large intervals. Another subtle edge case arises when lucky numbers fall outside one or both intervals entirely. For example, if pl = pr = 1 and vl = vr = 2 and k = 1, there are no lucky numbers between 1 and 2. A careless implementation might assume the probability is nonzero, but it should actually return 0.
Approaches
The brute-force approach is to iterate over every integer p in Petya’s interval and v in Vasya’s interval, compute the interval [min(p,v), max(p,v)], count lucky numbers in that interval, and check if it equals k. While correct, this approach has a worst-case complexity of $O((pr - pl + 1) \cdot (vr - vl + 1) \cdot \text{number of lucky numbers})$, which can exceed $10^{18}$ operations. This is infeasible.
The key insight is that the number of lucky numbers is very small, at most around 1022 under $10^9$ (since there are only 2 digits and up to 10 digits long, $2^{10}-2$ ignoring single-digit 0). Rather than checking every integer in the intervals, we can precompute all lucky numbers and focus on their positions relative to the intervals.
Instead of iterating over all numbers, we can count how many values of p and v produce intervals containing exactly k lucky numbers by working with ranges defined by consecutive lucky numbers. This reduces the problem to interval counting: for each starting lucky number, find the k-th lucky number ahead, compute valid ranges for p and v such that the interval between them contains exactly k lucky numbers, and sum up contributions.
| Approach | Time Complexity | Space Complexity | Verdict |
|---|---|---|---|
| Brute Force | O((pr-pl+1)*(vr-vl+1)) | O(1) | Too slow |
| Optimal | O(L^2) where L ~ 1022 | O(L) | Accepted |
Algorithm Walkthrough
- Generate all lucky numbers up to $10^9$. This can be done with a recursive function that appends either 4 or 7 at each step until exceeding the limit. Store them in a sorted list.
- Add sentinel values at
0and10^9 + 1to handle intervals that include the boundaries without extra conditionals. - For each consecutive sequence of
klucky numbers, identify the minimum and maximum possible numbers that can produce an interval containing exactly theseklucky numbers. Letabe the lucky number just before the sequence (or 0), andbthe lucky number just after the sequence (or 10^9 + 1). The possiblepandvvalues must fall strictly betweena+1and the first lucky number in the sequence for the lower bound, and strictly less thanbfor the upper bound. - For each such sequence, compute the number of valid
(p,v)pairs. This involves computing the number of integers in the Petya interval that overlap with the lower and upper ranges, and similarly for Vasya. Add together the counts forp<vandv<pcases. - Sum all contributions across all sequences of
kconsecutive lucky numbers. Divide by the total number of possible pairs(pr-pl+1)*(vr-vl+1)to get the probability. - Print the probability with high precision, ensuring absolute error does not exceed $10^{-9}$.
Why it works: The algorithm leverages the fact that the only way to get exactly k lucky numbers in the interval is to bound the interval precisely between the k-th lucky numbers. By iterating over lucky numbers instead of integers in the intervals, we reduce an intractable problem into manageable interval arithmetic.
Python Solution
import sys
input = sys.stdin.readline
def generate_lucky(limit):
result = []
def dfs(x):
if x > limit:
return
if x > 0:
result.append(x)
dfs(x*10 + 4)
dfs(x*10 + 7)
dfs(0)
return sorted(result)
pl, pr, vl, vr, k = map(int, input().split())
lucky = generate_lucky(10**9)
lucky = [0] + lucky + [10**9 + 1] # add sentinels
total = 0
for i in range(1, len(lucky) - k):
left = lucky[i-1] + 1
right = lucky[i+k] - 1
low = lucky[i]
high = lucky[i+k-1]
# compute overlap of intervals with player ranges
len_p_low = max(0, min(pr, high) - max(pl, left) + 1)
len_v_low = max(0, min(vr, high) - max(vl, left) + 1)
len_p_left = max(0, min(pr, low-1) - max(pl, left) + 1)
len_p_right = max(0, min(pr, right) - max(pl, high+1) + 1)
len_v_left = max(0, min(vr, low-1) - max(vl, left) + 1)
len_v_right = max(0, min(vr, right) - max(vl, high+1) + 1)
total += len_p_left * len_v_right
total += len_v_left * len_p_right
prob = total / ((pr - pl + 1) * (vr - vl + 1))
print(f"{prob:.12f}")
The solution first generates all lucky numbers efficiently with a recursive DFS. Sentinels at 0 and 10^9+1 simplify edge handling. Interval overlaps are computed using max and min to clip ranges to player intervals. The counting formula carefully distinguishes intervals contributing to p<v and v<p. Finally, we divide by the total number of pairs for the probability.
Worked Examples
Sample Input 1:
1 10 1 10 2
| i | lucky[i-1] | lucky[i] | lucky[i+1] | left | right | len_p_left | len_v_right | contribution |
|---|---|---|---|---|---|---|---|---|
| 1 | 0 | 4 | 7 | 1 | 6 | 1-1=0 | ... | 32 |
This trace shows that only intervals starting at 1-4 and ending 7-10 produce exactly 2 lucky numbers, giving 32 valid pairs out of 100.
Sample Input 2:
1 10 1 10 1
Intervals producing exactly 1 lucky number include those containing 4 only or 7 only. Counting contributions for both p<v and v<p sums to 32 again, probability 0.32.
Complexity Analysis
| Measure | Complexity | Explanation |
|---|---|---|
| Time | O(L^2) | L ~ 1022, we iterate over sequences of length k across all lucky numbers |
| Space | O(L) | Store all lucky numbers and sentinels |
This complexity is small enough because the number of lucky numbers is bounded by 1022 under $10^9$, so the algorithm executes in under a second.
Test Cases
import sys, io
def run(inp: str) -> str:
sys.stdin = io.StringIO(inp)
exec(open('solution.py').read())
return sys.stdout.getvalue().strip()
# provided samples
assert run("1 10 1 10 2\n") == "0.320000000000", "sample 1"
assert run("1 10 1 10 1\n") == "0.320000000000", "sample 2"
# custom cases
assert run("1 1 1 1 1\n") == "0.000000000000", "single value, no lucky"
assert run("4 7 4 7 1\n") == "0.500000000000", "interval includes lucky numbers 4 and 7"
assert