Анализ на задача nod

Тази задача ни затруднява с доста интересно нещо - кара ни да пишем решението ни в машинен код. Реално задачата ни логически ни представя пред друго предизвикателство - трябва да намерим НОД на две числа само с операции плюс и минус. Нека преминем към решенията:

Подзадача 1: а=1
В този случай единственият делител на а е едно, а както знаем всяко естествено число се дели на едно, затова просто трябва да върнем като отговор 1.

Подзадача 2: a, b<=5
Ограниченията ни позволяват да използваме какъвто и да е метод на "грубата сила".

Подзадача 3: a, b<=100
Тази подзадача няма специфично решение. Тя е просто поставена от нас за да възнагради участниците, които поради някаква причина пълното им решение е бавно или грешно.

Подзадача 4: a, b<=10^5
Тук се намира пълното решение на задачата. Ако някой знае алогиртъма на Евклид, би разбрал бързо как да я реши. Идеята на този древен алгоритъм се основава на следното нещо:
Ако имаме две положителни цели числа a и b, можем да повтаряме следното:

Ако a > b, замести a със a - b
Ако b > a, замести b със b - a
Повтаряме, докато a != b

Крайното ни число е НОД.

Нека дам и един пример:
Да намерим НОД(48, 18)

48 > 18 → 48 - 18 = 30 → (30, 18)
30 > 18 → 30 - 18 = 12 → (12, 18)
18 > 12 → 18 - 12 = 6 → (12, 6)
12 > 6 → 12 - 6 = 6 → (6, 6)

→ НОД = 6
Нека да докажем и защо е правилен:
Нека имаме две положителни цели числа a и b. Без загуба на общност приемаме, че a ≥ b.

Твърдение:

НОД(a, b) = НОД(a − b, b)

Доказателство:

Нека d е общ делител на a и b. Това означава:

d | a (d дели a)
d | b (d дели b)

Следователно:

d | (a − b)
(защото разликата на две числа, които се делят на d, също се дели на d)

→ d е общ делител и на a − b и b.

Обратно:
Ако d | (a − b) и d | b, тогава:

d | (a − b + b) = a

→ Значи d е общ делител на a и b.

Следствие:

Общите делители на (a, b) и (a − b, b) са едни и същи
→ НОД(a, b) = НОД(a − b, b).

Изводи: 
Затруднение в тази задача е, че трябва да се пише подобие на машинен код.
Друго затруднение в имплементацията е липсата на функция за безусловно прескачане към даден ред. 
Това може да се реши със сравнение на някое число с регистър, който не се използва и винаги приема стойност 0 → RES := 0, след което се използва инструкция JZ.

Автор и решения: Димитър Шапатов
Анализ: Кирил Зашев
