Find element position in given monotonic sequence

Given an integer k and a monotonic increasing sequence:
f(n) = an + bn [log2(n)] + cn^3 where (a = 1, 2, 3, …), (b = 1, 2, 3, …), (c = 0, 1, 2, 3, …)
Here, [log2(n)] means, taking the log to the base 2 and round the value down Thus,
if n = 1, the value is 0.
if n = 2-3, the value is 1.
if n = 4-7, the value is 2.
if n = 8-15, the value is 3.
The task is to find the value n such that f(n) = k, if k doesn’t belong to the sequence then print 0.
Note: Values are in such a way that they can be expressed in 64 bits and the three integers a, b and c do not exceed 100.

Examples:

Input: a = 2, b = 1, c = 1, k = 12168587437017
Output: 23001
f(23001) = 12168587437017

Input: a = 7, b = 3, c = 0, k = 119753085330
Output: 1234567890

Naive Approach: Given values of a, b, c, find values of f(n) for every value of n and compare it.

Efficient Approach: Use Binary Search, choose n = (min + max) / 2 where min and max are the minimum and maximum values possible for n then,

  • If f(n) < k then increment n.
  • If f(n) > k then decrement n.
  • If f(n) = k then n is the required answer.
  • Repeat the above steps until the required value is found or it is not possible in the sequence.

Below is the implementation of the above approach:

C++

filter_none

edit
close

play_arrow

link
brightness_4
code

// C++ implementation of the approach
#include <iostream>
#include <math.h>
#define SMALL_N 1000000
#define LARGE_N  1000000000000000
using namespace std;
  
// Function to return the value of f(n) for given values of a, b, c, n
long long func(long long a, long long b, long long c, long long n)
{
    long long res = a * n;
    long long logVlaue = floor(log2(n));
    res += b * n * logVlaue;
    res += c * (n * n * n);
    return res;
}
  
long long getPositionInSeries(long long a, long long b, 
                             long long c, long long k)
{
    long long start = 1, end = SMALL_N;
  
    // if c is 0, then value of n can be in order of 10^15.
    // if c!=0, then n^3 value has to be in order of 10^18
    // so maximum value of n can be 10^6.
    if (c == 0) {
        end = LARGE_N;
    }
    long long ans = 0;
  
    // for efficient searching, use binary search.
    while (start <= end) {
        long long mid = (start + end) / 2;
        long long val = func(a, b, c, mid);
        if (val == k) {
            ans = mid;
            break;
        }
        else if (val > k) {
            end = mid - 1;
        }
        else {
            start = mid + 1;
        }
    }
    return ans;
}
  
// Driver code
int main()
{
    long long a = 2, b = 1, c = 1;
    long long k = 12168587437017;
  
    cout << getPositionInSeries(a, b, c, k);
  
    return 0;
}

chevron_right


Python3

filter_none

edit
close

play_arrow

link
brightness_4
code

# Python 3 implementation of the approach 
from math import log2, floor
SMALL_N = 1000000
LARGE_N = 1000000000000000
  
# Function to return the value of f(n)
# for given values of a, b, c, n 
def func(a, b, c, n) :
      
    res = a * n
    logVlaue = floor(log2(n))
    res += b * n * logVlaue
    res += c * (n * n * n) 
    return res
  
def getPositionInSeries(a, b, c, k) :
      
    start = 1
    end = SMALL_N
  
    # if c is 0, then value of n 
    # can be in order of 10^15. 
    # if c!=0, then n^3 value has
    # to be in order of 10^18 
    # so maximum value of n can be 10^6. 
    if (c == 0) : 
        end = LARGE_N
      
    ans = 0
  
    # for efficient searching, 
    # use binary search. 
    while (start <= end) : 
          
        mid = (start + end) // 2
        val = func(a, b, c, mid)
        if (val == k) :
            ans = mid
            break
      
        elif (val > k) : 
            end = mid - 1
  
        else
            start = mid + 1
          
    return ans; 
  
# Driver code 
if __name__ == "__main__" :
      
    a = 2
    b = 1
    c = 1
    k = 12168587437017
  
    print(getPositionInSeries(a, b, c, k)) 
  
# This code is contributed by Ryuga

chevron_right


PHP

$k)
$end = $mid – 1;

else
$start = $mid + 1;
}
return $ans;
}

// Driver code
$a = 2;
$b = 1;
$c = 1;
$k = 12168587437017;

print(getPositionInSeries($a, $b, $c, $k));

// This code is contributed by mits
?>

Output:

23001


My Personal Notes arrow_drop_up