Подтвердить что ты не робот

Поиск общего количества битов с 1 по n

Напишите алгоритм, чтобы найти F(n) количество бит, установленное в 1, во всех числах от 1 до n для любого заданного значения n.

Сложность должна быть O(log n)

Например:

1: 001
2: 010
3: 011
4: 100
5: 101
6: 110

Итак,

F(1) = 1,  
F(2) = F(1) + 1 = 2,
F(3) = F(2) + 2 = 4,
F(4) = F(3) + 1 = 5,
etc.

Я могу только разработать алгоритм O(n).

4b9b3361

Ответ 1

Способ решения этих проблем состоит в том, чтобы записать первые несколько значений и искать шаблон

Number  binary   # bits set   F(n)
1       0001     1            1
2       0010     1            2
3       0011     2            4
4       0100     1            5
5       0101     2            7
6       0110     2            9
7       0111     3            12
8       1000     1            13
9       1001     2            15
10      1010     2            17
11      1011     3            20
12      1100     2            22
13      1101     3            25
14      1110     3            28
15      1111     4            32

Требуется немного взглянуть, но, с некоторыми соображениями, вы заметили, что двоичные представления первых 8 и последних 8 чисел точно такие же, за исключением того, что первые 8 имеют 0 в MSB (большинство значащий бит), а последние 8 имеют 1. Таким образом, например, чтобы вычислить F(12), мы можем просто взять F(7) и добавить к нему число установленных бит в 8, 9, 10, 11 и 12. Но это то же самое, что и число битов в 0, 1, 2, 3 и 4 (т.е. F(4)), плюс еще один для каждого числа!

#    binary
0    0 000
1    0 001
2    0 010
3    0 011
4    0 100
5    0 101
6    0 110
7    0 111

8    1 000  <--Notice that rightmost-bits repeat themselves
9    1 001     except now we have an extra '1' in every number!
10   1 010
11   1 011
12   1 100

Таким образом, для 8 <= n <= 15, F(n) = F(7) + F(n-8) + (n-7). Аналогично можно было бы отметить, что для 4 <= n <= 7, F(n) = F(3) + F(n-4) + (n-3); и для 2 <= n <= 3, F(n) = F(1) + F(n-2) + (n-1). В общем случае, если положить a = 2^(floor(log(n))), то F(n) = F(a-1) + F(n-a) + (n-a+1)


Это не совсем дает нам алгоритм O(log n); однако делать это легко. Если a = 2^x, то обратите внимание на приведенную выше таблицу, что для a-1 первый бит устанавливается ровно a/2 раз, второй бит устанавливается ровно a/2 раз, третий бит... полностью до x'th бит. Таким образом, F(a-1) = x*a/2 = x*2^(x-1). В приведенном выше уравнении это дает нам

F(n) = x*2x-1 + F(n-2x) + (n-2x+1)

Где x = floor(log(n)). Каждая итерация вычисления F существенно удалит MSB; таким образом, это алгоритм O(log(n)).

Ответ 2

Если n= 2^k-1, then F(n)=k*(n+1)/2

Для общего n пусть m - наибольшее число такое, что m = 2^k-1 и m<=n. F(n) = F(m) + F(n-m-1) + (n-m).

Условие угла: F(0)=0 и F(-1)=0.

Ответ 3

рассмотрим ниже:

0000
0001
0010
0011
0100
0101
0110
0111
1000
1001
1010
1011
1100
1101
1110
1111

Если вы хотите найти общее количество заданных бит от 1 до 14 (1110) Несколько наблюдений:

  • бит
  • 0th бит (LSB) 1 отображается один раз каждые два бита (см. вертикально), так что количество установленных бит = n/2 + (1, если n 0th bit is 1 else 0)
  • 1-й бит: 2 последовательных 1 появляются каждые четыре бита (см. 1-й бит по вертикали вдоль всех номеров) количество установленных битов в 1st бит position = (n/4 *2) + 1 (так как бит 1st - это set, else 0)
  • 2nd бит: 4 последовательный 1s появляется каждый бит 8 (этот бит немного сложнее) количество заданных битов во 2-й позиции = (n/8*4 )+ 1 (поскольку бит 2nd установлен, else 0) + ((n%8)%(8/2)) Последний член должен включать число 1s, которые были вне первой группы (n/8) бит (14/8 =1 учитывает только группу 1, т.е. 4 устанавливает биты в битах 8. Мы должны включить 1s найдено в последних 14-8 = 6 битах)
  • 3rd бит: 8 последовательные 1s появляются каждый бит 16 (аналогично выше) количество установленных бит в 3rd position = (n/16*8)+1 (поскольку бит 3rd установлен, else 0) + ((n%16)%(16/2))

поэтому мы делаем вычисление O(1) для каждого бита числа n. число содержит бит log2(n). поэтому, когда мы повторяем вышеперечисленное для всех позиций n и добавляем все установленные биты на каждом шаге, мы получаем ответ в шагах O(logn)

Ответ 4

Быстрый поиск значений последовательности F приводит к этой целочисленной последовательности http://oeis.org/A000788

Там я заметил формулу: a (0) = 0, a (2n) = a (n) + a (n-1) + n, a (2n + 1) = 2a (n) + n + 1 (a совпадает с F, так как я просто скопируйте формулу из oeis)

который может быть использован для вычисления a (n) в log (n).

Вот мой пример кода на С++:

memset(cache, -1, sizeof(cache))
cache[0] = 0

int f(int n)
    if cache[n] != -1 return cache[n];
    cache[n] = n % 2 ? (2 * f(n / 2) + n / 2 + 1) : (f(n / 2) + f(n / 2 - 1) + n / 2)

Ответ 5

Вот мое решение этого. Временная сложность: O (Log n)

public int countSetBits(int n){
    int count=0;
    while(n>0){
        int i= (int)(Math.log10(n)/Math.log10(2));
        count+= Math.pow(2, i-1)*i;
        count+= n-Math.pow(2, i)+1;
        n-= Math.pow(2, i);
    }
    return count;
}

Ответ 6

Пусть k - количество бит, необходимое для n.

для 0,...,2^(k-1)-1 каждый бит равен ровно для половины чисел, поэтому мы до сих пор биты (k-1)*2^(k-1)/2 = (k-1)*2^(k-2). Нам нужно только проверить, чем больше цифры, чем 2^(k-1)-1
Мы также имеем для этих n-2^(k-1)-1 бит "вверх" для MSB.

Таким образом, мы можем получить рекурсивную функцию:

f(n) = (k-1)*2^(k-2) + n-(2^(k-1)-1) + f(n-(2^(k-1)))
           ^               ^            ^
         first            MSBs        recursive call for 
       2^(k-1)-1                      n-2^(k-1) highest numbers
        numbers

Где база f(0) = 0 и f(2^k) = k*2^(k-1) + 1 [как мы видели раньше, мы точно знаем, сколько бит для 2^(k-1)-1, и нам просто нужно добавить 1 - для MSB 2^k]

Так как значение, отправленное на f, уменьшается на минимум на каждую итерацию, мы получаем общее количество O(logn)

Ответ 7

короткий и сладкий!

 public static int countbits(int num){
    int count=0, n;
    while(num > 0){
        n=0;
        while(num >= 1<<(n+1))
            n++;
        num -= 1<<n;
        count += (num + 1 + (1<<(n-1))*n);
    }
    return count;
}//countbis

Ответ 8

Вот java-функция

private static int[] findx(int i) {
    //find the biggest power of two number that is smaller than i
    int c = 0;
    int pow2 = 1;
    while((pow2<< 1) <= i) {
        c++;
        pow2 = pow2 << 1;
    }
    return new int[] {c, pow2};
}

public static int TotalBits2(int number) {
    if(number == 0) {
        return 0;
    }
    int[] xAndPow = findx(number);
    int x = xAndPow[0];
    return x*(xAndPow[1] >> 1) + TotalBits2(number - xAndPow[1]) + number - xAndPow[1] + 1;
}

Ответ 9

это закодировано в java...
логика: говорят, что число равно 34, двоичный равен ant равен 10010, который может быть записан как 10000 + 10. 10000 имеет 4 нуля, поэтому количество всех 1 до этого числа составляет 2 ^ 4 (причина ниже). поэтому счет равен 2 ^ 4 + 2 ^ 1 + 1 (номер его сам). поэтому ответ 35.
* для двоичного числа 10000. Общие комбинации заполнения 4 места составляют 2 * 2 * 2 * 2x2 (один или ноль). Таким образом, суммарные комбинации из них 2 * 2 * 2 * 2.

public static int getOnesCount(int number) {
    String binary = Integer.toBinaryString(number);
    return getOnesCount(binary);
}

private static int getOnesCount(String binary) {
    int i = binary.length();

    if (i>0 && binary.charAt(0) == '1') {
        return gePowerof2(i) + getOnesCount(binary.substring(1));
    }else if(i==0)
        return 1;
    else
        return getOnesCount(binary.substring(1));

}
//can be replaced with any default power function
private static int gePowerof2(int i){
    int count = 1;
    while(i>1){
        count*=2;
        i--;
    }
    return count;
}

Ответ 10

Кстати, этот вопрос также может быть сделан методом таблицы поиска. Предварительно сравните количество заданных бит с 0-255 и сохраните его. Положите, что мы можем вычислить количество заданных бит в любом числе, разбив заданное число на две части по 8 бит каждый. Для каждой части мы можем искать в массиве count, сформированном на первом этапе. Например, если есть 16-разрядное число, например,

x = 1100110001011100, здесь число заданных бит = количество заданных бит в первом байте + количество заданных бит во втором байте. Поэтому для получения первого байта

y = (x & 0xff) z = (x >> 8) & (0xff) total set bits = count[y] + count[z]

Этот метод будет работать и в O (n).

Ответ 11

Не уверен, если его поздно ответить, но вот мои выводы.

Пробовал решить проблему с помощью следующего подхода, для числа N каждый битно (от LSB до MSB, скажем, LSB начинается с битно 1 и увеличивается с последующим значением бита), количество битов может быть вычислено как (N/(2 topower битно) * (2 топора битно-1) + {(N% (2 топора битно)) - [(2 топора битно-1) - 1]}

Имейте письменную рекурсивную функцию для этого C/С++, пожалуйста, проверьте. Я не уверен, но я думаю, что его сложность - log (N). Параметр Pass function 2, номер (нет), для которого мы хотим, чтобы биты были вычислены, и второй стартовый счет из LSB, значение 1.

int recursiveBitsCal(int no, int bitno){
int res = int(no/pow(2,bitno))*int(pow(2,bitno-1));
int rem1 = int(pow(2,bitno-1)) -1;
int rem = no % int(pow(2,bitno));
if (rem1 < rem) res += rem -rem1;
if ( res <= 0 )
    return 0;
else
    return res + recursiveBitsCal(no, bitno+1);
}

Ответ 12

for i in range(int(input())):
    n=int(input())
    c=0
    m=13

    if n==0:
        print(c)
    while n%8!=0 or n!=0:
        t=bin(n)[2:]
        c+=t.count('1')
        n=n-1
    if n!=0:
        j=n//8
        if j==1:
            c+=m
        else:
            c+=m+((j-1)*7)
    print(c)        

Ответ 13

int countSetBits(int n)
{
    n++;
    int powerOf2 = 2;
    int setBitsCount = n/2;
    while (powerOf2 <= n)
    {
        int numbersOfPairsOfZerosAndOnes = n/powerOf2;
        setBitsCount += (numbersOfPairsOfZerosAndOnes/2) * powerOf2;
        setBitsCount += (numbersOfPairsOfZerosAndOnes&1) ? (n%powerOf2) : 0;
        powerOf2 <<= 1;
    }
    return setBitsCount;
}

Пожалуйста, проверьте мою статью на geeksforgeeks.org для подробного объяснения. Ниже ссылка на статьюhttps://www.geeksforgeeks.org/count-total-set-bits-in-all-numbers-from-1-to-n-set-2/

Ответ 14

Я знаю, что это сообщение пришло поздно на вечеринку, пожалуйста, найдите решение logn ниже:

static int countSetBitWithinRange(int n)
{
    int x = n + 1, index = 0, count = 0;
    int numberOfOnesInAGroup = (int)Math.pow(2, index);
    while(x >= numberOfOnesInAGroup)
    {
        int countOfZeroOnePairs = (x / numberOfOnesInAGroup);
        int numberOfPairsOfZerosAndOnes = countOfZeroOnePairs / 2;
        int numberOfSetBits = numberOfPairsOfZerosAndOnes * numberOfOnesInAGroup;
        //If countOfZeroOnePairs is even then the pairs are complete else there will be ones that do not have a corresponding zeros pair
        int remainder = (countOfZeroOnePairs % 2 == 1) ? (x % numberOfOnesInAGroup) : 0;
        count = count + numberOfSetBits + remainder;
        numberOfOnesInAGroup = 1 << ++index;
    }
    return count;
}

Ответ 15

x = int(input("Any number:\n"))
y = (bin(x))
print(y)
v = len(y) -2
print(v)