Article Categories
- All Categories
-
Data Structure
-
Networking
-
RDBMS
-
Operating System
-
Java
-
MS Excel
-
iOS
-
HTML
-
CSS
-
Android
-
Python
-
C Programming
-
C++
-
C#
-
MongoDB
-
MySQL
-
Javascript
-
PHP
-
Economics & Finance
Find element position in given monotonic sequence in Python
When working with monotonic sequences, we often need to find the position where a specific value occurs. This problem involves a monotonic increasing sequence defined by the function f(m) = am + bm[log?(m)] + cm³, where [log?(m)] represents the floor of log base 2.
Understanding the Formula
The sequence function f(m) = am + bm[log?(m)] + cm³ contains three components:
- Linear term: am (where a = 1, 2, 3, ...)
- Logarithmic term: bm[log?(m)] (where b = 1, 2, 3, ...)
- Cubic term: cm³ (where c = 0, 1, 2, 3, ...)
The floor logarithm [log?(m)] values are:
- m = 1: [log?(1)] = 0
- m = 2-3: [log?(m)] = 1
- m = 4-7: [log?(m)] = 2
- m = 8-15: [log?(m)] = 3
Binary Search Approach
Since the sequence is monotonic increasing, we can use binary search to efficiently find the position m where f(m) equals our target value l ?
from math import log2, floor
def solve(a, b, c, n):
"""Calculate f(n) = an + bn[log2(n)] + cn^3"""
ans = a * n
lg_val = floor(log2(n))
ans += b * n * lg_val
ans += c * n**3
return ans
def find_position(a, b, c, target):
"""Find position m where f(m) = target using binary search"""
SMALLER_VAL = 1000000
LARGER_VAL = 1000000000000000
begin = 1
end = SMALLER_VAL
# If no cubic term, extend search range
if c == 0:
end = LARGER_VAL
ans = 0
while begin <= end:
mid = (begin + end) // 2
val = solve(a, b, c, mid)
if val == target:
ans = mid
break
elif val > target:
end = mid - 1
else:
begin = mid + 1
return ans
# Example usage
a = 2
b = 1
c = 1
target = 12168587437017
result = find_position(a, b, c, target)
print(f"Position where f(m) = {target}: {result}")
Position where f(m) = 12168587437017: 23001
How the Algorithm Works
The algorithm uses binary search with adaptive bounds:
- Set initial bounds: Start with begin=1 and end=1,000,000
- Extend range if needed: If c=0 (no cubic term), extend end to 1,000,000,000,000,000
- Binary search: Calculate mid-point and evaluate f(mid)
- Adjust bounds: Move left if f(mid) > target, right if f(mid)
- Return result: Return position if found, otherwise 0
Testing Different Cases
from math import log2, floor
def solve(a, b, c, n):
ans = a * n
lg_val = floor(log2(n))
ans += b * n * lg_val
ans += c * n**3
return ans
def find_position(a, b, c, target):
SMALLER_VAL = 1000000
LARGER_VAL = 1000000000000000
begin = 1
end = SMALLER_VAL if c != 0 else LARGER_VAL
ans = 0
while begin <= end:
mid = (begin + end) // 2
val = solve(a, b, c, mid)
if val == target:
ans = mid
break
elif val > target:
end = mid - 1
else:
begin = mid + 1
return ans
# Test cases
test_cases = [
(2, 1, 1, 12168587437017), # Expected: 23001
(1, 1, 0, 10), # Linear + log case
(3, 2, 1, 100) # Small example
]
for a, b, c, target in test_cases:
result = find_position(a, b, c, target)
if result > 0:
verification = solve(a, b, c, result)
print(f"a={a}, b={b}, c={c}, target={target}")
print(f"Found position: {result}, f({result}) = {verification}")
else:
print(f"a={a}, b={b}, c={c}, target={target}: Not found")
print()
a=2, b=1, c=1, target=12168587437017 Found position: 23001, f(23001) = 12168587437017 a=1, b=1, c=0, target=10 Found position: 4, f(4) = 10 a=3, b=2, c=1, target=100 Found position: 4, f(4) = 100
Conclusion
Binary search is ideal for finding elements in monotonic sequences. The adaptive bounds handle different coefficient combinations efficiently, making this approach suitable for large search ranges up to 64-bit values.
