Я работал над проблемой Snapper Chain и пришел сюда, чтобы найти объяснение того, как алгоритм разбивки бит, с которым я столкнулся, работал. Я нашел хорошую информацию, но мне все равно понадобилось время, чтобы разобраться в этом, будучи побитым нобом.
Вот моя попытка объяснить алгоритм и как его найти. Если мы перечисляем все возможные мощности и состояния ВКЛ/ВЫКЛ для каждой привязки в цепочке, мы видим шаблон. Учитывая тестовый случай N = 3, K = 7 (3 окуней, 7 щелкает), мы показываем силу и ON/OFF состояние для каждого окуня на каждом КТНА оснастке:
1 2 3
0b:1 1 1.1 1.0 0.0 -> ON for n=1
0b:10 2 1.0 0.1 0.0
0b:11 3 1.1 1.1 1.0 -> ON for n=1, n=2
0b:100 4 1.0 0.0 1.0
0b:101 5 1.1 1.0 1.0 -> ON for n=1
0b:110 6 1.0 0.1 0.1
0b:111 7 1.1 1.1 1.1 -> ON for n=2, n=3
Лампочка горит, когда все окунь включены и получаются, или когда у нас есть k-я привязка, приводящая к n 1s.Еще проще, лампа включена, когда все окунители включены, так как все они должны получать питание, чтобы быть включенным (и, следовательно, лампочкой). Это означает, что для каждого k привязок требуется n 1s.
Кроме того, вы можете заметить, что k является двоичным числом не только для k = 7, которое удовлетворяет n = 3, но и для k = 3, которое удовлетворяет n = 2 и k = 1, которое удовлетворяет n = 1. Далее, для n = 1 или 2 мы видим, что каждое число привязок, которое включает лампу, последние n цифр k всегда 1. Мы можем попытаться обобщить, что все ks, которые удовлетворяют n snappers, будут двоичным числом, заканчивающимся на п цифры 1.
Мы можем использовать выражение, отмеченные ранее плакатом, чем 1 < < п - 1 всегда дает нам ˝n˝ двоичные цифры 1, или в данном случае, 1 < < 3 - 1 = 0b111. Если мы рассматриваем нашу цепочку n snappers как двоичное число, где каждая цифра представляет собой/выключена, и мы хотим n цифр одного, это дает нам наше представление.
Теперь мы хотим, чтобы найти те случаи, когда 1 < < п - 1 равно некоторому к, который заканчивается в п двоичных цифр 1, которые мы делаем, выполняя операции побитового и: к & (1 < < п - 1), чтобы получить последние n цифр k, а затем сравнив это с 1 < < n - 1.
Я полагаю, что этот тип мышления приходит более естественно после многих проблем с этими проблемами, но он все еще запугивает для меня, и я сомневаюсь, что когда-нибудь придумал такое решение!
Вот мое решение в Perl:
$tests = <>;
for (1..$tests) {
($n, $k) = split//, <>;
$m = 1 << $n - 1;
printf "Case #%d: %s\n", $_, (($k & $m) == $m) ? 'ON' : 'OFF';
}
, чтобы помочь вам относиться, напомним, '10000 - 1 = 9999', примерно то же самое происходит в двоичном – Anycorn
@aaa Действительно !. Теперь это имеет больше смысла. – srandpersonia
Я предпочитаю (k^(k + 1)) >> n –