Decibinary Numbers


Problem Statement :


Let's talk about binary numbers. We have an n-digit binary number, b, and we denote the digit at index  i(zero-indexed from right to left) to be bi. We can find the decimal value of b using the following formula:
   (b)2 => bn-1.2^(n-1) + ... + b2 . 2^2+ b1.2^1 + b0.2^0 = (?)10
For example, if binary number b = 10010, we compute its decimal value like so:
   (10010)2 => 1.2^4 + 0.2^3 + 0.2^2 + 1.2^1 + 0.2^0 = (18)10
Meanwhile, in our well-known decimal number system where each digit ranges from 0 to 9, the value of some decimal number, d, can be expanded in the same way:
   d = d(n-1).10^n-1 + ... + d1.10^2 + d1.1^1 + d0.10^0
Now that we've discussed both systems, let's combine decimal and binary numbers in a new system we call decibinary! In this number system, each digit ranges from 0 to 9 (like the decimal number system), but the place value of each digit corresponds to the one in the binary number system. For example, the decibinary number 2016 represents the decimal number 24 because:
   (2016)decibinary => 2.2^3 + 0.2^2 + 1.2^1 + 6.2^0 = (24)10
Pretty cool system, right? Unfortunately, there's a problem: two different decibinary numbers can evaluate to the same decimal value! For example, the decibinary number 2008 also evaluates to the decimal value 24:
   (2008)decibinary => 2.2^3 + 0.2^2 + 02^1 + 8.2^0 = (24)10
This is a major problem because our new number system has no real applications beyond this challenge!

Consider an infinite list of non-negative decibinary numbers that is sorted according to the following rules:

1.The decibinary numbers are sorted in increasing order of the decimal value that they evaluate to.
2.Any two decibinary numbers that evaluate to the same decimal value are ordered by increasing decimal value, meaning the equivalent decibinary values are strictly interpreted and compared as decimal values and the smaller decimal value is ordered first. For example, (2)decibinary and (10)decibinary both evaluate to (2)10. We would order (2)decibinary before (10)decibinary because (2)10 < (10)10.
Here is a list of first few decibinary numbers properly ordered:

image

You will be given q queries in the form of an integer, x. For each x, find and print the the xth decibinary number in the list on a new line.

Function Description

Complete the decibinaryNumbers function in the editor below. For each query, it should return the decibinary number at that one-based index.

decibinaryNumbers has the following parameter(s):

x: the index of the decibinary number to return
Input Format

The first line contains an integer, q, the number of queries.
Each of the next q lines contains an integer, x, describing a query.

Constraints

1 <= q <= 10^5
1 <= x <= 10^16



Solution :



title-img


                            Solution in C :

In C++ :






#include <iostream>
#include <algorithm>
#include <vector>
#include <map>
#include <string>
#include <cstring>
#include <cstdio>
#include <cmath>

using namespace std;

#define next next___

int s2[21];
unsigned long long Q[21][2600000];
unsigned long long W[2600000];
const int D = 20;

int main() {
    s2[0] = 1;
    for (int i = 1; i <= D; i++) {
        s2[i] = s2[i - 1] * 2;
    }
    Q[0][0] = 1;
    for (int i = 1; i <= D; i++) {
        int summ = min(9 * s2[i], 2600000);
        for (int sum = 0; sum < summ; sum++) {
            if (Q[i - 1][sum]) {
                for (int d = 0; d < 10; d++) {      
                    if (sum + d * s2[i - 1] < 2600000) {                              
                        Q[i][sum + d * s2[i - 1]] += Q[i - 1][sum];                
                    }
                }
            }
        }
    }

    W[0] = 1;
    for (int i = 1; i < 2600000; i++) {
        W[i] = W[i - 1] + Q[D][i];
    }        
    int q;
    cin >> q;
    while (q) {
        q--;
        unsigned long long x;
        cin >> x;
        if (x == 1) {
            cout << 0 << endl;
            continue;
        }
        int le = 0;
        int ri = 2600000;
        while (le + 1 < ri) {
            int mi = (le + ri) / 2;
            if (W[mi] >= x) {
                ri = mi;
            } else {
                le = mi;
            }
        }        
        x -= W[le];        
        long long ans = 0;
        for (int i = D; i >= 1; i--) {
            for (int d = 0; d < 10; d++) {
                if (Q[i - 1][ri - d * s2[i - 1]] >= x) {
                    ri -= d * s2[i - 1];
                    ans = ans * 10 + d;
                    break;
                }
                x -= Q[i - 1][ri - d * s2[i - 1]];
            }
        }
        cout << ans << endl;
    }
    
	return 0;
}








In Java :






import java.io.*;
import java.util.*;
import java.text.*;
import java.math.*;
import java.util.regex.*;

public class Solution {

    public static void main(String[] args) {
        int BITS = 19;
        int MAX = 1<<BITS;
        long[][] dp = new long[BITS][MAX];
        for (int i = 0; i < 10; i++)
            dp[0][i] = 1;
        for (int i = 1; i < BITS; i++) {
            int sub = 1<<i;
            for (int j = 0; j < MAX; j++) {
                for (int k = 0; k <= 9; k++) {
                    int rem = j-k*sub;
                    if (rem < 0)
                        break;
                    dp[i][j] += dp[i-1][rem];
                }
            }
        }
        long sum = 0;
        TreeMap<Long, Integer> sums = new TreeMap<Long, Integer>();
        sums.put(0l, -1);
        for (int i = 0; i < MAX; i++) {
            sum += dp[BITS-1][i];
            sums.put(sum, i);
        }
        Scanner sc = new Scanner(System.in);
        int q = sc.nextInt();
        for (int z = 0; z < q; z++) {
            long n = sc.nextLong();
            int val = sums.floorEntry(n-1).getValue()+1;
            n -= sums.floorEntry(n-1).getKey();
            long ans = 0;
            for (int i = BITS-1; i > 0; i--) {
                int digit = 0;
                while (dp[i-1][val] < n) {
                    n -= dp[i-1][val];
                    digit++;
                    val -= (1<<i);
                }
                ans *= 10;
                ans += digit;
            }
            ans *= 10;
            ans += val;
            System.out.println(ans);
        }
    }
}








In C :






#include <stdio.h>
#include <stdlib.h>
#define MAX 500000
int get_i(long long*a,long long num,int size);
long long med(long long*a,int size);
long long dp[30][MAX],sum[MAX],two[30];
unsigned long long ten[30];

int main(){
  int T,i,j,k;
  long long x,y,z;
  unsigned long long ans;
  for(i=two[0]=ten[0]=1;i<30;i++){
    two[i]=two[i-1]*2;
    ten[i]=ten[i-1]*10;
  }
  for(i=0,dp[0][0]=1;i<MAX;i++)
    for(j=1;j<30;j++)
      for(k=0;k<10;k++)
        if(k*two[j-1]<=i)
          dp[j][i]+=dp[j-1][i-k*two[j-1]];
  for(i=0;i<MAX;i++)
    if(i)
      sum[i]=sum[i-1]+dp[29][i];
    else
      sum[i]=dp[29][i];
  scanf("%d",&T);
  while(T--){
    scanf("%lld",&x);
    i=get_i(sum,x,MAX);
    if(i)
      y=x-sum[i-1];
    else
      y=x;
      //printf("i:%d y:%lld\n",i,y);
    for(j=29,ans=0;j>=0;j--)
      if(j)
        for(k=z=0;k<10;k++){
          z+=dp[j][i-k*two[j]];
          if(z>=y){
            y-=z-dp[j][i-k*two[j]];
            i-=k*two[j];
            ans+=k*ten[j];
      //printf("i:%d y:%lld\n",i,y);
            break;
          }
        }
      else
        ans+=i;
    printf("%llu\n",ans);
  }
  return 0;
}
int get_i(long long*a,long long num,int size){
  if(size==0)
    return 0;
  if(num>med(a,size))
    return get_i(&a[(size+1)>>1],num,size>>1)+((size+1)>>1);
  else
    return get_i(a,num,(size-1)>>1);
}
long long med(long long*a,int size){
  return a[(size-1)>>1];
}








In Python3 :





#!/bin/python3

import math
import os
import random
import re
import sys

# Complete the decibinaryNumbers function below.
power2=[1,2,4]

def init():
    
    #nb[decimal][m bits]

    d=[]
    nb=[]
    nb.append([])
    nb[0].append(1)
    d.append(1)
    nb.append([])
    nb[1].append(1)
    d.append(2)
    ind=2
    val=2
    decmax=9
    mmin=0
    mmax=1

    profondeur=16
    while ind<(10**profondeur):
        #nb[val]
        nb.append([])

        if val>decmax:
            mmin+=1
            decmax+=9*(power2[mmin])
        if val>=power2[mmax+1]:
            mmax+=1
            power2.append(power2[mmax]*2)
        if mmin>0:nb[val]=[0]*mmin
        else:nb[val].append(1)
        for m in range(max(mmin,1),mmax+1):
            temp,j,resul=val,0,0
            while temp>=0 and j<10:
                if (m-1)<len(nb[temp]):
                    resul+=nb[temp][m-1]
                else: resul+=nb[temp][-1]
                temp-=power2[m]
                j+=1
            nb[val].append(resul)
        ind+=nb[val][-1]
        d.append(ind)
        nb.append([])
        nb[val+1]=nb[val][:]
        ind+=nb[val+1][-1]
        d.append(ind)
        val+=2

    return d,nb

def decibinaryNumbers(x,d,nb):
    
    lowBound,highBound=0,len(d)
    while lowBound<highBound:
        mil=(lowBound+highBound)//2
        if d[mil]<x:
            lowBound=mil+1
        else:
            highBound=mil
    
    val=lowBound
    ind=d[val]
    if val==0:deb=0
    else:deb=d[val-1]

    return calcul(extraire(x-deb,val,nb))
    
def extraire(num,val,nb):
    if val==0: return [0]

    ind,nbBits=0,0
    while(num>nb[val][nbBits]): 
        nbBits+=1

    if nbBits==0:return [val]
    
    resul=[0]*(nbBits+1)    
    msb=0

    somme=nb[val][nbBits-1]
    prevVal,prevSomme,temp=0,0,val

    while(num>somme):
        msb+=1
        prevVal=temp
        temp-=power2[nbBits]
        prevSomme=somme
        if (nbBits-1)<len(nb[temp]):
            somme+=nb[temp][nbBits-1]
        else: somme+=nb[temp][-1]
    
    resul[-1]=msb
    aajouter=extraire(num-prevSomme,temp,nb)
    
    for i in range(len(aajouter)): resul[i]=aajouter[i]

    return resul

def calcul(liste):
    
    resul=0
    power10=1
    for l in liste:
        resul+=l*power10
        power10*=10
    return resul


if __name__ == '__main__':
    fptr = open(os.environ['OUTPUT_PATH'], 'w')

    q = int(input())
    d,nb=init()

    for q_itr in range(q):
        x = int(input())

        result = decibinaryNumbers(x,d,nb)

        fptr.write(str(result) + '\n')

    fptr.close()
                        








View More Similar Problems

Array Pairs

Consider an array of n integers, A = [ a1, a2, . . . . an] . Find and print the total number of (i , j) pairs such that ai * aj <= max(ai, ai+1, . . . aj) where i < j. Input Format The first line contains an integer, n , denoting the number of elements in the array. The second line consists of n space-separated integers describing the respective values of a1, a2 , . . . an .

View Solution →

Self Balancing Tree

An AVL tree (Georgy Adelson-Velsky and Landis' tree, named after the inventors) is a self-balancing binary search tree. In an AVL tree, the heights of the two child subtrees of any node differ by at most one; if at any time they differ by more than one, rebalancing is done to restore this property. We define balance factor for each node as : balanceFactor = height(left subtree) - height(righ

View Solution →

Array and simple queries

Given two numbers N and M. N indicates the number of elements in the array A[](1-indexed) and M indicates number of queries. You need to perform two types of queries on the array A[] . You are given queries. Queries can be of two types, type 1 and type 2. Type 1 queries are represented as 1 i j : Modify the given array by removing elements from i to j and adding them to the front. Ty

View Solution →

Median Updates

The median M of numbers is defined as the middle number after sorting them in order if M is odd. Or it is the average of the middle two numbers if M is even. You start with an empty number list. Then, you can add numbers to the list, or remove existing numbers from it. After each add or remove operation, output the median. Input: The first line is an integer, N , that indicates the number o

View Solution →

Maximum Element

You have an empty sequence, and you will be given N queries. Each query is one of these three types: 1 x -Push the element x into the stack. 2 -Delete the element present at the top of the stack. 3 -Print the maximum element in the stack. Input Format The first line of input contains an integer, N . The next N lines each contain an above mentioned query. (It is guaranteed that each

View Solution →

Balanced Brackets

A bracket is considered to be any one of the following characters: (, ), {, }, [, or ]. Two brackets are considered to be a matched pair if the an opening bracket (i.e., (, [, or {) occurs to the left of a closing bracket (i.e., ), ], or }) of the exact same type. There are three types of matched pairs of brackets: [], {}, and (). A matching pair of brackets is not balanced if the set of bra

View Solution →