Comments 34
D = p1n1 × p2n2 ×… × pknk
Количество различных комбинаций этих множителей даст количество проходов, на которых дверь сменит состояние. Его можно получить как
N = (n1 + 1) × (n2 + 1) ×… × (nk + 1)
Для того, чтобы дверь в конце осталась открытой она должна сменить своё состояние нечётное количество раз. Такое возможно только если все множители (ni + 1) будут нечётными, то есть все ni будут чётными.
Но, раз все ni — чётные, то мы можем записать изначальное разложение как
D = (p1n1/2)2 × (p2n2/2)2 ×… × (pknk/2)2 = (p1n1/2 × p2n2/2 ×… × pknk/2)2
Таким образом, открытыми останутся только двери, чьи номера представляют собой квадраты целых чисел, то есть 1, 4, 9, 16, 25, 36, 49, 64, 81, 100.
public bool IsPowerOfTwo(int Number) { return ((Number & 1) == 0) ? IsPowerOfTwo(Number >> 1) : Number == 1; }
static int SearchInLeftPart(int[] Arr, int Number)
{
int BreakPointMin = Arr[Arr.Length - 1];
int BreakPointMax = Arr[0];
int Left = 0;
int Right = Arr.Length - 1;
int Med;
while (Left < Right)
{
Med = (Left + Right) / 2;
if (Arr[Med] == Number) return Med;
if (Arr[Med] <= BreakPointMin)
{
Right = Med - 1;
continue;
}
if (Arr[Med] > Number)
{
Right = Med - 1;
}
else
{
Left = Med + 1;
}
}
if (Arr[Left] == Number) return Left;
return -1;
}
static int SearchInRightPart(int[] Arr, int Number)
{
int BreakPointMin = Arr[Arr.Length - 1];
int BreakPointMax = Arr[0];
int Left = 0;
int Right = Arr.Length - 1;
int Med;
while (Left < Right)
{
Med = (Left + Right) / 2;
if (Arr[Med] == Number) return Med;
if (Arr[Med] >= BreakPointMax)
{
Left = Med + 1;
continue;
}
if (Arr[Med] > Number)
{
Right = Med - 1;
}
else
{
Left = Med + 1;
}
}
if (Arr[Left] == Number) return Left;
return -1;
}
static public int SearchInArr(int[] Arr, int Number)
{
int BreakPointMin = Arr[Arr.Length - 1];
int BreakPointMax = Arr[0];
if (BreakPointMin > BreakPointMax) return Array.BinarySearch(Arr, Number);
if (Number > BreakPointMin && Number < BreakPointMax) return -1;
if (Number <= BreakPointMin) return SearchInRightPart(Arr, Number);
else return SearchInLeftPart(Arr, Number);
}
static int[] GetNumbers(int N)
{
List<int> res = new List<int>();
int Order = 1;
int tmp = N;
while (tmp/10 != 0)
{
Order++;
tmp /= 10;
}
int start = N - Order * 9;
if (start < 0) start = 0;
for (int i = start; i < N; i++)
{
if (i+ GetSumOfDigits(i) == N)
{
res.Add(i);
}
}
return res.ToArray();
}
static int GetSumOfDigits(int N)
{
int res = 0;
while (N / 10 != 0)
{
res += N%10;
N /= 10;
}
res += N;
return res;
}
По второму вопросу: так как там лампы, можно попытаться определить по нагреву — горячая, теплая, бе нагрева — только причем тут программирование…
По первой задаче: в одну строку можно посчитать количество бит в числе — если равно 1 то степень двойки.
По второй задаче: глядя на первый и последний элементы возможно можно узнать точку поворота.
По второй задаче: глядя на первый и последний элементы возможно можно узнать точку поворота.
Однако, тоже за логарифмическое время (см. задачу за прошлую неделю). А потом второй проход по одному из двух подмассивов. Если сохранить значения из первого прохода, можно, наверное, немного сэкономить на втором.
По второму вопросу: так как там лампы, можно попытаться определить по нагреву — горячая, теплая, бе нагрева — только причем тут программирование…В этом случае, условие задачи не полное, т.к. не исключает вариант, что лампы висят на высоте 5 метров и нет никаких подручных средств, чтобы их достать.
По первому вопросу: посещение двери равно её порядковому номеру.
Сколько раз посещали двери под номерами 3,5,7,11,13....?
bool function isPowerOf2(int number) { return !(number & (number - 1)); }
TL;DR
И почему решение, к которому вы меня подталкиваете, основывается на недокументированных и ненадежных побочных явлениях? Неужели ваша команда пишет код, корректность которого основывается на недокументированных и ненадежных взаимосвязях, которые могут на порядок отличаться в зависимости от деталей реализации?
2 вопрос. Баян, и вообще вопрос многими считается не корректным.
1. Задача. Отнимаем от числа 1, и побитово умножаем с исходным числом.
2. Задача. Опять повороты массивов. Смысл давать похожие задачи между 2-мя выпусками?
Над последней задачей ещё думаю.
f 0 a 0 = [a]
f 0 _ _ = []
f d a n | c > 9 = []
| c == 0 = [c] >>= f'
| otherwise = [c, c-1] >>= f' where
d1 = d + 1
c = div n d1
d' = div d 10
f' v = f d' (v:a) (n-v*d1)
toi = foldr (\x a -> a*10 + x) 0
g n = map toi . f (10^(length $ show n)) [] $ n
main = do
mapM (\x -> putStrLn $ show x ++ " " ++ show (g x)) [10000000000000..10000000000010]
Find a Number X whose sum with its digits is equal to N
def f(N):
res = []
for x in range(max(N - 9 * len(str(N)), 1), N):
if x + sum(map(int, str(x))) == N:
res.append(x)
print(f'N = {N}, X : {res or [-1]}')
f(21)
f(5)
f(100000001)
вывод
N = 21, X : [15]
N = 5, X : [-1]
N = 100000001, X : [99999937, 100000000]
Имхо, получается только первый вопрос более-менее нетривиален, учитывая что ответ надо дать не кодом а в результате устных рассуждений. Ну и третья задача допускает алгоритм, немного интереснее очевидного (опубликовал выше).
Про лампочки — баян (к тому же спорный), про степень двойки — трижды баян, но далеко не все языки дают доступ к битовому представлению чисел, поэтому альтернативный однострочник
f n = n==1 || r==0 && f q where (q,r) = quotRem n 2
про сортированный массив — тоже очевидно.
Но для школьников старших классов вполне подходящие задачки на факультатив.
Не знаю, была ли подобная задача тут или нет.
В комнате находится шахматная доска, на каждой клетке которой лежит по одной монете.
Первый участник заходит в комнату и узнает "ключевую" клетку.
Он может перевернуть не более одной любой монеты.
Задача второго участника найти "ключевую" клетку.
Попытка передать информацию с помощью сдвига монеты к краю, поворота, царапин и т.п. недопустима.
2) уже видел когда-то. Один выключатель нужно включить на время и выключить, чтобы найти соответствие по температуре.
1. if (sumarray(char a[] = (string(binary(x)))) == 1) then println(«power of two!»)
2. ищем пивот как в прошлонедельной задаче. Дальше переопределяем начало кольца этим пивотом. Всё, массив вернули в исходное состояние, для которого уже было готовое решение за такое время.
3. Положим, на входе 7 значное число. Максимум, который могут дать цифры в сумме — это 6 девяток и первая цифра числа — 1. Отступим от числа на 6*9+первая_цифра-1, и переберём небольшое число вариантов. Количество проверяемых чисел — пропорционален логарифму от входного числа. Проверка суммы цифр так же пропорциональна длине чисел, так что всего получаем быстроту O((log(N))^2).
Глядя на этот ряд у меня возникает два вопроса: существует ли аналитический способ получить его? И почему он всё ещё содержит весь правильный ряд, как если бы мы делали прогоны в одну сторону? Если поменять количество дверей (я пробовал 101, чётные, нечйтные, полные квадраты и простые) то можно избавится от последней сотни, но на дальней перспективе, уже к 81, все меньшие полные квадраты сохраняются… Так странно… Очень не похоже на совпадение.
Но это если бы чувак ходил каждый раз в одном направлении, но тут явно имеется в виду что он ходит туда — обратно так что я сразу так не могу придумать формулу
Но решить задачу это не показатель. На их решения обычно натаскивают. Не тривиальных задач довольно мало. Остальные решаются по известным алгоритмам. Поэтому основная проблема — отнести задачу к соответствующему типу задач.
P.S. Утверждаю это как бывший преподаватель высшей математики, готовила и к олимпиадным задачам и к ЕГЭ.
Выпуск#10: ITренировка — актуальные вопросы и задачи от ведущих компаний