Арифметическая прогрессия
От: Аноним  
Дата: 29.11.02 09:58
Оценка:
В файле записаны неповторяющиеся числа.
Необходимо за один проход и без использования массивов определить, можно ли их записать в виде арифметической прогрессии.
Например

2 10 8 6 4
можно представить в виде
2 4 6 8 10 — арифметическая прогрессия d=2

Числа
1 3 5 9 11, нельзя — пропущена 7


16.01.03 23:38: Перенесено из 'Алгоритмы'
Re: Арифметическая прогрессия
От: UgN  
Дата: 29.11.02 10:29
Оценка:
Здравствуйте, Аноним, Вы писали:

А>В файле записаны неповторяющиеся числа.

А>Необходимо за один проход и без использования массивов определить, можно ли их записать в виде арифметической прогрессии.
А>Например

А>2 10 8 6 4

А>можно представить в виде
А>2 4 6 8 10 — арифметическая прогрессия d=2

А>Числа

А>1 3 5 9 11, нельзя — пропущена 7


Проходишь по файлу и одновременно делаешь слудующее:

1. Запоминаешь наименьшее число Min
if (Value < Min) Min = Value;

2. Запоминаешь наибольшее число Max
if (Value > Max) Max = Value;

3. Запоминаешь наименьшую по модулю разность между двумя соседними числами Diff
if (CurDiff < Diff) Diff = CurDiff;

4. Запоминаешь количество чисел в файле. Cnt
Cnt++

Потом
return  ( ( ( Max - Min ) / Cnt ) == Diff ) ? true : false;
Re[2]: Арифметическая прогрессия
От: TheGrey Украина http://www.uoi.kiev.ua
Дата: 29.11.02 10:41
Оценка:
Здравствуйте, UgN, Вы писали:

UgN>1. Запоминаешь наименьшее число Min

UgN>2. Запоминаешь наибольшее число Max
UgN>3. Запоминаешь наименьшую по модулю разность между двумя соседними числами Diff
UgN>4. Запоминаешь количество чисел в файле. Cnt
UgN>Потом
UgN>
UgN>return  ( ( ( Max - Min ) / Cnt ) == Diff ) ? true : false;
UgN>


Это неправильно. Причем проколы в двух местах

Контр-пример: 2 8 4 10 6
1. Min = 2
2. Max = 10
3. Diff = 4
4. (10-2)/4 != 4

А это — арифметическая прогрессия.
Re[2]: Арифметическая прогрессия
От: Аноним  
Дата: 29.11.02 10:46
Оценка:
Здравствуйте, UgN, Вы писали:

Берем 2 8 4 10 6 — можно написать 2 4 6 8 10

UgN>

UgN>Проходишь по файлу и одновременно делаешь слудующее:

UgN>1. Запоминаешь наименьшее число Min


Min = 2

UgN>
UgN>if (Value < Min) Min = Value;
UgN>

UgN>2. Запоминаешь наибольшее число Max

Max = 10

UgN>
UgN>if (Value > Max) Max = Value;
UgN>

UgN>3. Запоминаешь наименьшую по модулю разность между двумя соседними числами Diff
UgN>
UgN>if (CurDiff < Diff) Diff = CurDiff;
UgN>


Dif = 4;

UgN>4. Запоминаешь количество чисел в файле. Cnt

UgN>
UgN>Cnt++
UgN>


Cnt = 5

UgN>Потом

UgN>
UgN>return  ( ( ( Max - Min ) / Cnt ) == Diff ) ? true : false;

(10 - 2) / 4 = 2
Diff = 4
Результат false
Облом :(
Но мысль есть :)

UgN>
Re[2]: Исправленное и дополненное
От: UgN  
Дата: 29.11.02 11:03
Оценка:
3. Запоминаешь наименьшую по модулю разность между первым и последующими числами Diff
Потом
return  ( ( ( Max - Min ) / ( Cnt - 1 ) ) == Diff ) ? true : false;


Re: Арифметическая прогрессия
От: Bell Россия  
Дата: 29.11.02 11:03
Оценка:
Здравствуйте, Аноним, Вы писали:

А>В файле записаны неповторяющиеся числа.

А>Необходимо за один проход и без использования массивов определить, можно ли их записать в виде арифметической прогрессии.

За один проход ищем минимальное и максимальное число и сумму всех чисел(ну и заодно запоминаем количество чисел, если не было известно заранее)
берем формулу для суммы элементов прогресси, считаем, и сверяем с полученной ранее суммой.
Любите книгу — источник знаний (с) М.Горький
Re[3]: Исправленное и дополненное
От: Atilla Россия  
Дата: 29.11.02 11:07
Оценка:
Здравствуйте, UgN, Вы писали:


UgN>3. Запоминаешь наименьшую по модулю разность между первым и последующими числами Diff

UgN>Потом
UgN>
UgN>return  ( ( ( Max - Min ) / ( Cnt - 1 ) ) == Diff ) ? true : false;
UgN>


UgN>


а так:

2 4 5 6 10

Cnt=5, Min=2, Max=10, Diff=2
(10-2)/(5-1)==2!  :)

?
Кр-ть — с.т.
Re[2]: Арифметическая прогрессия
От: Atilla Россия  
Дата: 29.11.02 11:09
Оценка:
Здравствуйте, Bell, Вы писали:

B>За один проход ищем минимальное и максимальное число и сумму всех чисел(ну и заодно запоминаем количество чисел, если не было известно заранее)

B>берем формулу для суммы элементов прогресси, считаем, и сверяем с полученной ранее суммой.


1 2 3 3 6 6 7 8 9 10

сумма=55, сумма_по_формуле=55


?
Кр-ть — с.т.
Re[2]: Арифметическая прогрессия
От: seug  
Дата: 29.11.02 11:12
Оценка:
UgN>3. Запоминаешь наименьшую по модулю разность между двумя соседними числами Diff
UgN>
UgN>if (CurDiff < Diff) Diff = CurDiff;
UgN>

В этом месте надо считать не минимальную разность 2 соседних чесел, а первого и последующих.

UgN>4. Запоминаешь количество чисел в файле. Cnt

UgN>
UgN>Cnt++
UgN>

А так же сумму всех чисел

Sum += Value;


А потом проверяем
if (((Max-Min)/(Cnt-1) != Diff) return false;
if (Min*Cnt + Diff*Cnt*(Cnt-1)/2 != Sum) return false;
return true;
Re[4]: Исправленное и дополненное 2
От: UgN  
Дата: 29.11.02 11:18
Оценка:
Изверги!




3.1 Запоминаешь наименьшую по модулю разность между первым и последующими числами DiffA
3.2 Запоминаешь наименьшую по модулю разность между соседними числами DiffB

Если DiffA > DiffB, то это фигня, а не прогрессия

Потом

return  ( ( ( Max - Min ) / ( Cnt - 1 ) ) == Diff ) ? true : false;
Re[3]: Арифметическая прогрессия
От: Atilla Россия  
Дата: 29.11.02 11:18
Оценка:
Контрпример уже есть здесь
Автор: Atilla
Дата: 29.11.02
Кр-ть — с.т.
Re[3]: Арифметическая прогрессия
От: Bell Россия  
Дата: 29.11.02 11:19
Оценка:
Здравствуйте, Atilla, Вы писали:


Смотреть условие внимательно!!!
Любите книгу — источник знаний (с) М.Горький
Re[3]: Арифметическая прогрессия - исправлено
От: seug  
Дата: 29.11.02 11:22
Оценка:
Здравствуйте, seug, Вы писали:

UgN>>3. Запоминаешь наименьшую по модулю разность между двумя соседними числами Diff

UgN>>
UgN>>if (CurDiff < Diff) Diff = CurDiff;
UgN>>

В этом месте надо считать не минимальную разность 2 соседних чесел, а НОД разностей
Diff = gcd(Diff, CurDiff);



UgN>>4. Запоминаешь количество чисел в файле. Cnt

UgN>>
UgN>>Cnt++
UgN>>

А так же сумму всех чисел

Sum += Value;


А потом проверяем делится ли Diff на шаг прогрессии а так же сумму чисел и сумму прогрессии на раыенство
d = (Max-Min)/(Cnt-1);
if (Diff%d != 0) return false;
if (Min*Cnt + d*Cnt*(Cnt-1)/2 != Sum) return false;
return true;
Re[4]: Арифметическая прогрессия - исправлено
От: Atilla Россия  
Дата: 29.11.02 11:25
Оценка:
Здравствуйте, seug, Вы писали:


S>В этом месте надо считать не минимальную разность 2 соседних чесел, а НОД разностей


о! вот теперь правильно.
Только можно не сумму считать, а минимум и максимум.
Кр-ть — с.т.
Re: Арифметическая прогрессия
От: TheGrey Украина http://www.uoi.kiev.ua
Дата: 29.11.02 11:26
Оценка:
Здравствуйте, Аноним, Вы писали:

А>В файле записаны неповторяющиеся числа.

А>Необходимо за один проход и без использования массивов определить, можно ли их записать в виде арифметической прогрессии.

Вариант А.

1. Находим минимальное a_1
2. Находим второе по величине a_2. d=a_2-a_1.
3. Находим максимальное a_n
4. Находим НОД всех разниц пар чисел, которые идут подряд в последовательности.
5. Считаем n

Утверждение. Если НОД делится на d и a_n=a_1+(n-1)*d, то а.п., иначе — не а.п.

Обоснование. То что НОД делится на d обозначает что модуль разницы любой пары чисел последовательности не больше d.

Вариант Б.

1. Находим минимальное a_1
2. Находим второе по величине a_2. d=a_2-a_1.
3. Находим сумму всех чисел S
4. Находим произведение всех чисел P
5. Считаем n

Сумма S и произведение P должны совпадать с суммой а.п. с первым членом a_1 и разницей d.

Пока обосновать строго не получилось. Но интуитивно — вроде так.

Контрпримеры?
Re[4]: Арифметическая прогрессия
От: Atilla Россия  
Дата: 29.11.02 11:27
Оценка:
Здравствуйте, Bell, Вы писали:

B>Здравствуйте, Atilla, Вы писали:


B>

B>Смотреть условие внимательно!!!

ну это уже детали


3 6 10 11 15


тем более правильный ответ уже прозвучал
Кр-ть — с.т.
Re[5]: Арифметическая прогрессия - исправлено
От: seug  
Дата: 29.11.02 11:27
Оценка:
Здравствуйте, Atilla, Вы писали:

A>Здравствуйте, seug, Вы писали:


A>

S>>В этом месте надо считать не минимальную разность 2 соседних чесел, а НОД разностей

A>о! вот теперь правильно.

A>Только можно не сумму считать, а минимум и максимум.

Какже ты предлагаешь обойтись без суммы?
А минимум и максимум и так считаются.
Re: Арифметическая прогрессия
От: Кодт Россия  
Дата: 29.11.02 11:29
Оценка:
Здравствуйте, Аноним, Вы писали:

А>В файле записаны неповторяющиеся числа.

А>Необходимо за один проход и без использования массивов определить, можно ли их записать в виде арифметической прогрессии.

Пусть мы даже не знаем изначально количество чисел (текстовый файл).
Что мы можем измерить за один проход...

Для прогрессии с шагом D, разность d[i,j] двух любых членов a[i], a[j] равна (j-i)*D.
Следовательно, НОД(d1,d2) = k*S. НОД(всех d) = D.
Достаточно приложиться к разностям соседних чисел файла.
D = |f[1]-f[0]|
for i = 2 .. end_of_file
D = НОД(D, |f[i]-f[i-1]|)

Далее, если мы насчитали N чисел, то для прогрессии выполняется |a_max-a_min| == (N-1)*D.
(минимальное и максимальное числа находятся элементарно)

Критерий недостаточный: контрпример: 1 2 3 5 3 6 7 8
Однако для неповторяющихся чисел, возможно, он достаточен (надо подумать...)

Еще один критерий.
Сумма прогрессии S = a[0]+...+a[N-1] = a_min + N*(N-1)/2*D.
(сумма чисел считается за этот же проход)

Критерий также недостаточный: 1 2 7 2 7 2 7 8
Та же самая ремарка.
Перекуём баги на фичи!
Re[4]: Арифметическая прогрессия
От: Bell Россия  
Дата: 29.11.02 11:29
Оценка:
Здравствуйте, Atilla, Вы писали:

A>Контрпример уже есть здесь
Автор: Atilla
Дата: 29.11.02


Читаем условие задачи: В файле записаны неповторяющиеся числа...
Так что этот контрпример не соответствует условию.
Любите книгу — источник знаний (с) М.Горький
Re[6]: Арифметическая прогрессия - исправлено
От: Atilla Россия  
Дата: 29.11.02 11:57
Оценка:
Здравствуйте, seug, Вы писали:

S>Какже ты предлагаешь обойтись без суммы?


Ну как, есть массив
a0, a1, ... an

считаем в 1 проход max(a), min(a), и D=НОД(a[i+1]-a[1])

получается, что a[i+1]-a[i]=D*k[i+1] или
a[i]=a[0]+(k[1]+...k[i])*D

пусть шаг прогрессии равен C*D, C>1, тогда любая разность будет делиться на C*D и НОД!=D.
или так: a[i]=Min+D*K[i], т.е. шаг прогрессии (если она имеет место быть) d может быть только делителем.
Альтернатива — прогрессии нет, а есть подпоследовательность прогрессии с шагом d, которая — делитель D. Вот...

Пусть D=C*d, C>1
возьмем полную последовательность от min до max с шагом d.
а {a} — это на самом деле подпоследовательность, которая не является арифметической с шагом D.
Т.е. существует по крайнем мере один элемент a[x]=min+d*X, причем d*X не делится на D. Тогда, т.к. разница с соседями делится на D, то соседние тоже такие: a[x-1]=min+d*X1, a[x+1]=min+d*X2, где d*X1 и d*X2 не делятся на D.
Ну и аналогично, получается, что каждый элемент a[i]=min+d*Xi, причем d*Xi не делится на D для всех i, даже для минимума. Ну а такое — невозможно.
Остается последний вариант: {a} — подпоследовательность ар. прогрессии с шагом D. Проверить это — элементарно:
если (min-max)/(n-1)=D, то прогрессия, иначе — подпоследовательность

вроде нигде не наврал

S>А минимум и максимум и так считаются.


легко
Кр-ть — с.т.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.