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.
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++
#include <iostream>
#include <math.h>
#define SMALL_N 1000000
#define LARGE_N 1000000000000000
using namespace std;
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 == 0) {
end = LARGE_N;
}
long long ans = 0;
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;
}
int main()
{
long long a = 2, b = 1, c = 1;
long long k = 12168587437017;
cout << getPositionInSeries(a, b, c, k);
return 0;
}
|
Java
import java.util.*;
class GFG {
static long SMALL_N = 1000000 ;
static Long LARGE_N = Long.parseUnsignedLong( "1000000000000000" );
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 == 0 ) {
end = LARGE_N;
}
long ans = 0 ;
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;
}
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));
}
}
|
Python3
from math import log2, floor
SMALL_N = 1000000
LARGE_N = 1000000000000000
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 = = 0 ) :
end = LARGE_N
ans = 0
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;
if __name__ = = "__main__" :
a = 2
b = 1
c = 1
k = 12168587437017
print (getPositionInSeries(a, b, c, k))
|
C#
using System;
using System.Collections.Generic;
class GFG {
static long SMALL_N = 1000000;
static long LARGE_N = 1000000000000000;
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 == 0) {
end = LARGE_N;
}
long ans = 0;
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;
}
public static void Main( string [] args)
{
long a = 2, b = 1, c = 1;
long k = 12168587437017;
Console.WriteLine(getPositionInSeries(a, b, c, k));
}
}
|
PHP
<?php
$SMALL_N = 1000000;
$LARGE_N = 1000000000000000;
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 == 0)
$end = $LARGE_N ;
$ans = 0;
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 ;
}
$a = 2;
$b = 1;
$c = 1;
$k = 12168587437017;
print (getPositionInSeries( $a , $b , $c , $k ));
?>
|
Javascript
<script>
const SMALL_N = 1000000;
const LARGE_N = 1000000000000000;
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 == 0)
{
end = LARGE_N;
}
let ans = 0;
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;
}
let a = 2, b = 1, c = 1;
let k = 12168587437017;
document.write(getPositionInSeries(a, b, c, k));
</script>
|
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.
Last Updated :
26 Feb, 2023
Like Article
Save Article
Share your thoughts in the comments
Please Login to comment...