İkinci testi nəzərdən keçirin. Hər bir ədədin -ə bölünməsində qalanı nədir?
Üçü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.
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?
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:
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:
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ə
Çü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ə
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:
Bəzən bu formada hesablamalar daha rahat olur.
Misal
Birinci test üçün aşağıdakı nəticəni alırıq:
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:
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);
}