Розгляньте другий тест. Чому рівні остачі при діленні кожного числа на ?
Розгляньте третій тест. Чому рівні остачі при діленні кожного числа на ? Згадайте, як обчислюються остачі при діленні від'ємних чисел на додатні.
Нехай — найбільше число, для якого при діленні всіх чисел a_i на отримуються однакові остачі. Що можна сказати про різницю будь-яких двох чисел послідовності відносно числа ?
Подайте числа a_i у вигляді a_i = d \cdot r_i + rest і розгляньте різниці a_{i+1} - a_i. Якому найбільшому значенню задовольняють ці рівняння? Згадайте визначення найбільшого спільного дільника.
Аналіз алгоритму
Нехай дана послідовність чисел: a_1, a_2, ..., a_k.
Якщо при діленні кожного числа a_i~(1 \le i \le k) на остача однакова, позначимо цю остачу як . Тоді кожне число можна записати у вигляді:
Тут r_1, r_2, ..., r_k — цілі числа (частки від ділення).
Тепер вирахуємо сусідні елементи послідовності:
У всіх цих різницях число є множником. Значить, ділить кожну з різниць: a_2 - a_1, a_3 - a_2, ..., a_k - a_{k-1}.
Ми шукаємо максимальне можливе , що ділить всі ці різниці. За визначенням, найбільше число, що ділить кілька чисел одночасно, — це їх найбільший спільний дільник (НСД). Отже
Оскільки вибрано максимальним, то числа r_2 - r_1, r_3 - r_2, ... не мають спільного дільника більше . Інакше цей спільний дільник можна було б винести, збільшивши , що суперечить його максимальності. Таким чином
Зазначимо також, що якщо, наприклад, з кожного рівняння виду a_i = d \cdot r_i + rest~(2 \le i \le k) віднімемо перше, то відповідь можна записати у наступному вигляді:
Іноді обчислення в такому вигляді є більш зручними.
Приклад
Для першого тесту отримаємо:
Реалізація алгоритму
Функція gcd обчислює найбільший спільний дільник двох чисел і .
int gcd(int a, int b)
{
return (!b) ? a : gcd(b, a % b);
}Основна частина програми. Читаємо перше число a_1. Якщо воно дорівнює , значить це останній рядок і він не обробляється — виходимо з циклу.
while (scanf("%d", &a), a)
{Змінна зберігає поточний результат — найбільший спільний дільник різниць.
res = 0;Читаємо чергове число рядка у змінну . Відповідь обчислюємо за формулою
У коді змінна зберігає значення a_1, а змінна приймає значення a_2, a_3, ..., a_k.
while (scanf("%d", &b), b)
res = gcd(res, abs(b - a));Виводимо відповідь.
printf("%d\n", res);
}