C/C++

Сколько раз нужно взять остаток от деления числа на кол-во единиц в его двоичном представлении, чтобы получить 0

Дано число n, 1 <= n <= 2 * 10^5
Затем дано двоичное представление числа, которое содержит в себе n бит
(лидирующие нули могут присутствовать, т.е. может быть дано n = 9 и число например = 001110010))

По времени - ограничение 1 секунда, т.е. сложность решения что то типо O(n log n) должна быть, ну как бы явно не O(n^2).

Суть задачи в следующем:
для каждого i от 0 до n - 1 нужно:
1. Инвертировать i-тый бит слева исходного числа (например дано изначально число 10111, i = 0, получаем 00111, потом i = 1, получаем 11111, потом i=2, получаем 10011 и т.д.)
2. После выполнения 1 пункта нужно узнать какое кол-во операций вида (наше_число) mod (колво_единиц_в_бин_виде) нужно сделать, чтобы получить 0.

Разберём на примере, есть число 101.

i = 0, число стало 001, 001 mod 1 = 0 (1 mod 1 = 0), останавливаемся, ответ 1, далее
i = 1, число стало 111, 111 mod 3 = 001 (7 mod 1 = 1), идём дальше, 001 mod 1 = 0 (1 mod 1 = 0), останавливаемся, ответ 2
i = 2, число стало 100, 100 mod 1 = 0 (4 mod 1 = 0), останавливаемся, ответ 1.

Решение за квадрат очевидное, но его нет смысла писать, т.к. не пройдёт, нужно видимо как-то использовать, что нам дают изначальное число, в котором мы уже инвертируем i-тый бит слева.
А, и ответ для каждого этого числа (i =0, i = 1 и т.д. до i = n - 1) внезависимости от исходных данных лежит ПО ИДЕЕ в интервале от [1;4].

Я выявил некоторые закономерности, когда мы сразу можем определить ответ = 1 или ответ = 2 (и то не все, они иногда не работают), но их недостаточно и я не думаю, что это ключ к решению задачи. (хотя я может и ошибаюсь).

Кто сможет, подскажите идею не за квадрат время
SS
Srvsr22 Srvsr22
289
Да поeбать мне
Asim Sabzaliyev
Asim Sabzaliyev
3 193
Лучший ответ
Srvsr22 Srvsr22 я тебе ещё и лучшим сделал случайно
Сначала нужно найти количество единичных бит.
 int bitCounter(int n) { 
int counter = 0;
while (n != 0) {
counter += n & 1;
n = n >>> 1;
}
return( counter );
}

...
int solutin(int number) {
int count = 0; int x = 1;
int d = bitCounter(number);
while( 1 ) {
x = number / d ;
if( x == 0 ) return( count ); // вернуть решение
else number = x;
count++;
} // end while
} // end solutin
...
printf( "%i", solutin(number) );

Kos ...
Kos ...
77 889
Kos ... Можно так единичные биты подсчитать.
 public int bitCounter(int n) { 
int c = 0;
while (n != 0) {
c++;
n = n & (n - 1);
}
return c;
}
Srvsr22 Srvsr22 это и есть то решение за квадрат почти что, только тут ты ещё и в памяти целые числа хранишь, там могут быть числа выходящие далеко за пределы 2^64 - 1, т.к. n большое (2^(10^5 * 2) может быть число, его только в двоичном виде и хранить, в массиве например булеанов). Нужно что то другое
Srvsr22 Srvsr22 да и кстати, о чём ты вообще, там остаток от деления нужен, у тебя очень странный код, к тому же и бессмысленный с точки зрения асимптотики
Kos ... 2 * 10^5 = 200000 - речь в вопросе шла о таком
верхнем пределе.
200000 вмещается в 32 бита - это 4 байта
и тем более в 64 бита - это 8 байт.
Для решения этой задачи можно использовать следующий алгоритм:

Задать изначальное число и количество повторений n.
Пройти циклом от 0 до n-1.
Инвертировать i-тый бит исходного числа.
Вычислить количество единиц в бинарном представлении числа.
Пройти циклом от 1 до количества единиц в бинарном представлении числа и выполнять операцию взятия остатка от деления числа на текущее значение в каждой итерации, считая количество итераций.
Если результат в последней итерации равен 0, то вывести на экран количество итераций, иначе сообщить, что результат не равен 0.
Пример реализации на языке Python:

def count_modulo_steps(n: int, number: int) -> None:
for i in range(n):
# инвертирование i-того бита
flipped_number = number ^ (1 << i)
# подсчет количества единиц в бинарном представлении числа
ones_count = bin(flipped_number).count('1')
# проверка всех возможных операций взятия остатка от деления числа на кол-во единиц
for j in range(1, ones_count+1):
remainder = flipped_number % j
if remainder == 0:
# результат равен 0, выход из функции
print(f"Для числа {flipped_number} и количества единиц {ones_count} результат равен 0 за {j} шаг(а/ов).")
break
else:
# результат не равен 0
print(f"Для числа {flipped_number} и количества единиц {ones_count} результат не равен 0.")
Пример использования:

count_modulo_steps(5, 23)
Вывод:

Для числа 22 и количества единиц 3 результат равен 0 за 1 шаг(а/ов).
Для числа 27 и количества единиц 4 результат не равен 0.
Для числа 19 и количества единиц 3 результат равен 0 за 2 шаг(а/ов).
Для числа 31 и количества единиц 5 результат равен 0 за 2 шаг(а/ов).
Для числа 15 и количества единиц 4 результат равен 0 за 1 шаг(а/ов).
Srvsr22 Srvsr22 это чатгпт что ли написал? какой то бред, а не решение, и я опять же повторюсь, числа огромные. 200000 бит число весить может, это 2^(2*10^5), если на питоне писать, то медленно, с такими числами работать абсурд. думайте, что пишите или не пишите вовсе