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:

  1. Set initial bounds: Start with begin=1 and end=1,000,000
  2. Extend range if needed: If c=0 (no cubic term), extend end to 1,000,000,000,000,000
  3. Binary search: Calculate mid-point and evaluate f(mid)
  4. Adjust bounds: Move left if f(mid) > target, right if f(mid)
  5. 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.

Updated on: 2026-03-25T09:37:30+05:30

336 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements