Last active
April 16, 2018 18:32
-
-
Save AnthonyMikh/5f5a3c5b2d91f4bb37a3be7aaa4caa27 to your computer and use it in GitHub Desktop.
Решение задачи №85 от UniLecs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
solve k = | |
if k == 0 | |
then 0 | |
else extract . dropWhile (notSameOddity k') . dropWhile (notIncludes k') . enhance $ [0..] | |
where | |
k' = abs k | |
sums = scanl (+) 0 [1..] | |
enhance = zip3 (cycle [0, 1, 1, 0]) sums | |
first (x, _, _) = x | |
second (_, x, _) = x | |
third (_, _, x) = x | |
notIncludes k = (< k) . second | |
notSameOddity k = (/= k `rem` 2) . first | |
extract = third . head | |
assertEq x y = | |
if x == y | |
then return () | |
else error $ "Assertion violated: first argument is " ++ show x ++ " but second argument is " ++ show y | |
assertEq' = uncurry assertEq | |
main = do | |
assertEq' (solve 2, 3) | |
assertEq' (solve 12, 7) | |
putStrLn "Tests passed" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Назовём последовательность вида
,
где
△
является+
либо-
,op(n)
-последовательностью.Обозначим через
S(n)
множество значенийop(n)
последовательностей при всех возможных подстановках △.Теорема 1: для любого неотрицательного
n
элементыS(n)
либо все чётные, либо все нечётные.Доказательство: воспользуемся методом математической индукции.
Базис индукции: при
n = 0
S(n) = {0}
, т. е. все элементы чётные.Шаг индукции: пусть все элементы
S(n - 1)
имеют одинаковую чётность.op(n)
можно получить, приписав△ n
кop(n - 1)
. Любое число вS(n)
получается прибавлением или вычитаниемn
к некоторому числуk
изS(n - 1)
. Еслиn
чётное, тоk △ n
имеет ту же чётность, что иk
. Если жеn
нечётное, тоk △ n
иk
имеют противоположные чётности. В любом случае оба полученных числа имеют одинаковую чётность. С учётом того, что все числаS(n - 1)
имеют одинаковую чётность, получаем, что и вS(n)
все числа имеют одинаковую чётность. ◼Определим функцию
Теорема 2: функция
oddity(n)
является периодической, и её период равен 4.Доказательство: рассмотрим величину
m = n mod 4
.Если
m = 0
илиm = 3
(n = 4*k или n = 4*k + 3, k ∈ ℤ
), то значениеop(n)
является суммой чётных чисел и чётного числа нечётных чисел, поэтому значениеop(n)
чётное.Если
m = 1
илиm = 2
(n = 4*k + 1 или n = 4*k + 2, k ∈ ℤ
), то значениеop(n)
является суммой чётных чисел и нечётного числа нечётных чисел, поэтому значениеop(n)
нечётное.Так как функция
n mod 4
является периодической с периодом4
, то такой же период имеет функцияoddity
. ◼Обозначим

Теорема 3:
S(n)
— множество всех целых чисел отрезка[-sumfirst(n), sumfirst(n)]
с той же чётностью, что иsumfirst(n)
.Доказательство: воспользуемся методом математической индукции.
Базис индукции: при
n = 0
S(n) = {0}
, и все чётные точки из[-n, n] = [0, 0] = {0}
принадлежатS(0)
.Шаг индукции: пусть при
n = k -1
∀a: a ∈ ℤ ∩ [-sumfirst(-(k - 1)), sumfirst(k - 1)], a mod 2 = sumfirst(k -1) mod 2 ⇔ a ∈ S(k -1)
.m ∈ [-sumfirst(k), sumfirst(k)]
такое, чтоm mod 2 = sumfirst(k) mod 2
. Допустим, чтоm ∉ S(k)
.Если
m ≥ 0
, положимm̃ = m - k
, иначе положимm̃ = m + k
.Если
m ≥ 0
, тоТ. о.,
m̃
принадлежит множеству целых чисел отрезка[-sumfirst(k - 1), sumfirst(k - 1)]
с той же чётностью, что иsumfirst(k -1)
. Тогда согласно посылке шага индукцииm̃ ∈ S(k-1)
. Но тогдаm = m̃ + k = op(k - 1) + k = 0 △ 1 △ … △ (k -1) + k = op(k)
, и, следовательно,m ∈ S(k)
, что противоречит нашему предположению. Следовательно, наше исходное предположение неверно иm ∈ S(k)
. Случайm < 0
рассматривается аналогично.Т. о. мы получаем, что для любого
m ∈ [-sumfirst(k), sumfirst(k)]
такого, чтоm mod 2 = sumfirst(k) mod 2
справедливоm ∈ S(k)
.2) Рассмотрим произвольное
m ∈ S(k)
. В силу определенияS(k)
m ∈ [-sumfirst(k), sumfirst(k)]
.m mod 2 = (0 △ 1 △ … △ (k -1) △ k) mod 2 = sumfirst(k) mod 2
. Следовательно,m
принадлежит множеству целых чисел отрезка[-sumfirst(k), sumfirst(k)]
с той же чётностью, что иsumfirst(k -1)
◼Из вышесказанного следует следующая простая идея решения: для данного
k
берём наименьшееn
, для которого[-sumfirst(n), sumfirst(n)]
включает|k|
, а затем при необходимости корректируемn
так, чтобы выполнялосьoddity(n) = k mod 2
. Согласно теореме 2, для этого понадобится увеличитьn
максимум на 2.Так как компьютеры работают не с настоящими действительными числами, а с их аппроксимацией, вычислять
n
через неравенствоsumfirst(n) >= k
нежелательно, потому что при вычислении ответа используется квадратный корень, а для большихk
значение квадратного корня может быть искажено отбрасыванием последних битов, не умещающихся в разрядную сетку. Во избежание ошибок подобного рода генерируется последовательность{sumfirst(0), sumfirst(1), sumfirst(2), …}
, последовательные элементы которой сравниваются сk
.