Sadə Bölmə#1182

Sadə Bölmə (Həll təhlili)

  1. İkinci testi nəzərdən keçirin. Hər bir ədədin -ə bölünməsində qalanı nədir?

  2. Üçüncü testi nəzərdən keçirin. Hər bir ədədin -ə bölünməsində qalanı nədir? Mənfi ədədlərin müsbət ədədlərə bölünməsində qalıqların necə hesablandığını unutmayın.

  3. Gəlin — bütün a_i ədədlərinin bölünməsində eyni qalıqların alındığı ən böyük ədəd olsun. -yə nisbətən ardıcıllıqda olan istənilən iki ədədin fərqi haqqında nə deyə bilərsiniz?

  4. a_i ədədlərini a_i = d \cdot r_i + rest formasında təqdim edin və a_{i+1} - a_i fərqlərini nəzərdən keçirin. Bu bərabərliklərə hansı ən böyük qiyməti uyğundur? Ən böyük ortaq bölən tərifini xatırlayın.

Alqoritmin analizi

Məsələn, ədədlər ardıcıllığı verilmişdir: a_1, a_2, ..., a_k.

Əgər hər bir a_i~(1 \le i \le k) ədədinin -yə bölünməsində qalıq eynidirsə, bu qalığı kimi işarə edək. Onda hər bir ədəd aşağıdakı formada göstərilə bilər:

a_1 = d \cdot r_1 + rest \\ a_2 = d \cdot r_2 + rest \\ ... \\ a_k = d \cdot r_k + rest

Burada r_1, r_2, ..., r_k — tam ədədlərdir (bölünmənin nəticələri).

İndi ardıcıllığın qonşu elementlərini çıxaq:

a_2 - a_1 = d \cdot (r_2 - r_1) \\ a_3 - a_2 = d \cdot (r_3 - r_2) \\ ... \\ a_k - a_{k-1} = d \cdot (r_k - r_{k-1})

Bu bütün fərqlərdə çarpandır. Deməli, hər bir fərqdə a_2 - a_1, a_3 - a_2, ..., a_k - a_{k-1} bölür.

Biz bu fərqləri bölən mümkün ən böyük axtarırıq. Tərifə görə, bir neçə ədədi eyni zamanda bölən ən böyük ədəd onların ən böyük ortaq bölənidir (ƏOB). Nəticədə

d = ƏOB(|a_2 - a_1|, |a_3 - a_2|, ..., |a_k - a_{k-1}|)

Çünki maksimal olaraq seçilib, deməli r_2 - r_1, r_3 - r_2, ... yanaşmasının ortaq böləni -dən böyük deyildir. Əks halda, bu ortaq böləni çıxarmaq, -ni artırmaq olardı ki, bu onun maksimalığına təzad təşkil edir. Nəticədə

ƏOB(r_1, r_2, ..., r_n) = 1

Qeyd edək ki, əgər məsələn, bəzi a_i = d \cdot r_i + rest~(2 \le i \le k) tənliklərdən birincini çıxsaq, cavabı aşağıdakı formada yaza bilərik:

d = ƏOB(|a_2 - a_1|, |a_3 - a_1|, ..., |a_k - a_1|)

Bəzən bu formada hesablamalar daha rahat olur.

Misal

Birinci test üçün aşağıdakı nəticəni alırıq:

d = ƏOB(|1059 - 701|, |1417 - 1059|, |2312 - 1417|) = ƏOB(358, 358, 895) = 179.

Alqoritmin reallaşdırılması

gcd funksiyası iki ədədin və -nin ən böyük ortaq bölənini hesablayır.

int gcd(int a, int b)
{
  return (!b) ? a : gcd(b, a % b);
}

Proqramın əsas hissəsi. Birinci ədəd a_1-ni oxuyuruq. Əgər o, -a bərabərdirsə, deməli bu sonuncu sətirdir və bu işlə təhlükə edilmir — dövrədən çıxırıq.

while (scanf("%d", &a), a)
{

dəyişəni cari nəticəni saxlayır — fərqlərin ən böyük ortaq böləni.

  res = 0;

Növbəti sətirin ədədini dəyişənində oxuyuruq. Cavab aşağıdakı tənzimlə hesablanır:

d = ƏOB(|a_2 - a_1|, |a_3 - a_1|, ..., |a_k - a_1|)

Kodda dəyişəni a_1 qiymətini saxlayır, dəyişəni isə a_2, a_3, ..., a_k qiymətləri alır.

  while (scanf("%d", &b), b)
    res = gcd(res, abs(b - a));

Cavabı çıxar.

  printf("%d\n", res);
}