Open In App

Find element position in given monotonic sequence

Last Updated : 26 Feb, 2023
Comments
Improve
Suggest changes
Like Article
Like
Report

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.

Time Complexity: O(n)

Space Complexity: O(1)

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++
// 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;
}
Java
// Java implementation of the approach

import java.util.*;

class GFG {
    static long SMALL_N = 1000000;
    static Long LARGE_N = Long.parseUnsignedLong("1000000000000000");

    // Function to return the value of f(n) for given values
    // of a, b, c, n
    static long func(long a, long b, long c, long n)
    {
        long res = a * n;
        long logVlaue = (long)(Math.log(n) / Math.log(2));
        res += b * n * logVlaue;
        res += c * (n * n * n);
        return res;
    }

    static long getPositionInSeries(long a, long b, long c,
                                    long k)
    {
        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 ans = 0;

        // for efficient searching, use binary search.
        while (start <= end) {
            long mid = (start + end) / 2;
            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
    public static void main(String[] args)
    {
        long a = 2, b = 1, c = 1;
        Long k = Long.parseUnsignedLong("12168587437017");

        System.out.println(getPositionInSeries(a, b, c, k));
    }
}

// This code is contributed by phasing17
Python3
# 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
C#
// C# implementation of the approach

using System;
using System.Collections.Generic;

class GFG {
    static long SMALL_N = 1000000;
    static long LARGE_N = 1000000000000000;

    // Function to return the value of f(n) for given values
    // of a, b, c, n
    static long func(long a, long b, long c, long n)
    {
        long res = a * n;
        long logVlaue = (long)(Math.Log(n) / Math.Log(2));
        res += b * n * logVlaue;
        res += c * (n * n * n);
        return res;
    }

    static long getPositionInSeries(long a, long b, long c,
                                    long k)
    {
        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 ans = 0;

        // for efficient searching, use binary search.
        while (start <= end) {
            long mid = (start + end) / 2;
            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
    public static void Main(string[] args)
    {
        long a = 2, b = 1, c = 1;
        long k = 12168587437017;

        Console.WriteLine(getPositionInSeries(a, b, c, k));
    }
}

// This code is contributed by phasing17
PHP
<?php
// PHP 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 
function func($a, $b, $c, $n) 
{
    $res = $a * $n; 
    $logVlaue = floor(log($n, 2)); 
    $res += $b * $n * $logVlaue; 
    $res += $c * ($n * $n * $n); 
    return $res; 
}

function getPositionInSeries($a, $b, $c, $k) 
{ 
    global $SMALL_N, $LARGE_N;
    $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 = (int)(($start + $end) / 2);
        $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 
$a = 2;
$b = 1;
$c = 1;
$k = 12168587437017;

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

// This code is contributed by mits 
?>
JavaScript
<script>

// Javascript implementation of the approach
const SMALL_N = 1000000;
const LARGE_N = 1000000000000000;

// Function to return the value of f(n) 
// for given values of a, b, c, n
function func(a, b, c, n)
{
    let res = a * n;
    let logVlaue = Math.floor(Math.log(n) / 
                              Math.log(2));
    res += b * n * logVlaue;
    res += c * (n * n * n);
    return res;
}

function getPositionInSeries(a, b, c, k)
{
    let 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;
    }
    let ans = 0;

    // For efficient searching, use binary search.
    while (start <= end)
    {
        let mid = parseInt((start + end) / 2);
        let 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
let a = 2, b = 1, c = 1;
let k = 12168587437017;

document.write(getPositionInSeries(a, b, c, k));

// This code is contributed by souravmahato348

</script>

Output: 
23001

 


Time Complexity: O(log n), since it's a binary search where each time the elements are reduced to half.
Auxiliary Space: O(1), since no extra space has been taken.


Article Tags :

Similar Reads