Арифметическая прогрессия
От: Аноним  
Дата: 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>А минимум и максимум и так считаются.


легко
Кр-ть — с.т.
Re[7]: Ну и где этот Инвалид?
От: Atilla Россия  
Дата: 29.11.02 16:33
Оценка:
Т.е. Аноним. Хоть сказал бы, правильный ответ или нет...
Кр-ть — с.т.
Re[2]: Арифметическая прогрессия : доказательство!
От: Кодт Россия  
Дата: 29.11.02 17:07
Оценка:
Немного к вопросу о доказательствах.

Пусть мы нашли НОД всех смежных разностей (а также всех разностей с первым, с локально минимальным, с локально максимальным элементами — сколько угодно).
Тогда, без потери общности задачи, мы можем взять эквивалентный файл, такой, что его минимальный элемент = 0 (т.е. вычли f_min из всех элементов f), а НОД равен 1 (поделили (f-f_min) на НОД).

То есть свели задачу к такой: можно ли для набора разных неотрицательных чисел определить — является ли он арифметической прогрессией вида 0,1,2,...k...

Ответ: конечно, да!
Предположим, что у нас N чисел (и все они разные по условиям задачи; мы это утверждение дополнительно не проверяем!).
Тогда они будут являться указанной прогрессией тогда и только тогда, когда минимум = 0, а максимум = N-1.
Доказательство очевидно: пусть в наборе есть "щербина" (отсутствуют некоторые числа прогрессии). Тогда, если минимум = 0 и максимум = M-1, то количество N будет меньше, чем M.
А если щербины нет, то M==N.
Повторяться числа не могут по условию, поэтому вариант N>M, а также компенсация щербин повторами невозможна.

Теперь вернем все на место: каждый элемент натуральной прогрессии умножим на D и прибавим f_min.

Таким образом, алгоритм проверки найден:
1) находим D = НОД((f[0]-f[k]) для всех k), f_min, f_max, N
2) проверяем f_min + D*(N-1) == f_max.

В нашем доказательстве мы исходили из того, что D>0 (делили и умножали на него). Очевидно, что случай D==0 говорит о том, что одна из разностей оказалась нулевой, то есть в файле встретился повтор.
Перекуём баги на фичи!
Re[3]: Арифметическая прогрессия : доказательство!
От: Atilla Россия  
Дата: 29.11.02 18:16
Оценка:
А здесь
Автор: Atilla
Дата: 29.11.02
что, плохое доказательство?
Кр-ть — с.т.
Re[4]: Арифметическая прогрессия : доказательство!
От: Кодт Россия  
Дата: 29.11.02 18:29
Оценка:
Здравствуйте, Atilla, Вы писали:

A>А здесь
Автор: Atilla
Дата: 29.11.02
что, плохое доказательство?


У тебя акценты по-другому расставлены.

Большую часть работы ты проводишь, чтобы сказать: все числа (относительно первого) кратны шагу прогрессии, который был найден как НОД всех разностей. Это как бы масло масляное: все разности кратны НОД от их всех

Меня же как раз волновало доказательство того, что (N-1)*D=(max-min) есть необходимое и достаточное условие (которое ты упомянул всколзь).
Перекуём баги на фичи!
Re[5]: Арифметическая прогрессия : доказательство!
От: Atilla Россия  
Дата: 29.11.02 19:06
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Большую часть работы ты проводишь, чтобы сказать: все числа (относительно первого) кратны шагу прогрессии, который был найден как НОД всех разностей. Это как бы масло масляное: все разности кратны НОД от их всех


Просто я долго не мог понять, это очевидно или не очень
Как говорил мой школьный учитель (покайный ) "очевидное — это то, что легко доказать". Вот я и решил доказать.

К>Меня же как раз волновало доказательство того, что (N-1)*D=(max-min) есть необходимое и достаточное условие (которое ты упомянул всколзь).


Ну а это, по-моему и ежу понятно. Если шаг прогрессии может быть только D и никак иначе, то проверка сразу получается.


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