1. Наконец-то на сайте заработал форум! Там вы
можете попросить консультацию по решению задчи,
обсудить алгоритм, поделиться впечатлениями с
олимпиады, и ещё много чего;). Заходите, будем
рады!
2. Наш проект становиться довольно
популярным в Рунете. Рамблер на запрос
"олимпиадные задачи по информатике" наш
сайт sapisoft.by.ru выводит на первое(!) место. И это при
том, что я раскрутке времени практически не
уделял ;].
3. Меня не будет с недельку, так что вы не
скучайте;). И про сайт не забывайте. Можете пока на
форуме пообщаться...
Письма читателей:
Я
конечно думал, что заметка про обмен значений
переменных вызовет некоторое количество
замечаний, но в таком объёме...;[]
From:
Andy Ice <AndyIce@mail.ru>
To: sapisoft@yandex.ru
Date: Thursday, March 14, 2002, 11:32:19 AM
Subject: Олимпиадные задачи с решениями на Turbo Pascal
Хотелось бы предостеречь от явной ошибки в
данном алгоритме. Дело в том, информатика - это,
все таки, не "чистая математика", и возможно
сразу же в первой строчке получить ошибку
переполнения.
Пример:
a, b: Byte;
a0 := 250;
b0 := 200;
Результат?
From:
Andrew Ezhguroff <eandr@com2com.ru>
To: sapisoft@yandex.ru
Date: Thursday, March 14, 2002, 11:29:42 AM
Subject: Обмен значений переменных
Здравствуйте.
Если в языке возможны битовые операции с целыми
числами (не знаю, есть ли это в TP), то subj можно
записать забавнее:
From:
zugr <zugr@unikon-ua.net>
To: sapisoft@yandex.ru
Date: Thursday, March 14, 2002, 2:10:18 PM
Subject: Обмен значений переменных
А на С это ищё красивее:
a^=b;
b^=a;
a^=b;
:-)
From:
Boris Bukh <brbukh@yahoo.com>
To: sapisoft@yandex.ru
Date: Thursday, March 14, 2002, 6:20:58 PM
Subject: Неточность в теории
Hello,
В последней рассылке неточность в разделе
теория. Если использовать +,- то тогда если
нечайно откомпилировать прогу с проверкой
переполнения, то тогда можете получить run-time error в
самый неприятный момент. Лучше пользоваться xor.
Проблемы в том что это работает только на
целочисленных и булевых переменных, а вот на
вещественных как быть? Ваш прием на вещественных
также не пройдет еще по причине
неассоциативности сложения в компьютерной
арифметики. Предлагаю выставить эту задачу в
раздел "Нерешенные задачи".
From:
Serhiy Serbin <serhiys@adarvo.com>
To: sapisoft@yandex.ru
Date: Friday, March 15, 2002, 9:32:38 AM
Subject: Обмен значений переменных
Привет, то что придумали давно не спорю :)) Но
знать должен каждый :)) Есть еще один вариант, по
идее должен роботать быстрее:
a = a ^ b;
b = a ^ b;
a = b ^ a;
, где = - оператор присваивания, а ^ - xor. К
сожалению Паскакаль не знаю, так что в его
нотации записать не могу.
Best regards,
Serhiy Serbin
From:
Alex <malex@ua.fm>
To: sapisoft@yandex.ru
Date: Friday, March 15, 2002, 2:45:38 PM
Subject: Обмен значений переменных
Hi!
хорошая рассылка! только imho: 1 - мало:(, 2 - только
самые известные проблемы!
в рассылке от 11.03.2002 был известный пример Сабжа от
HellMan
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
procedure swap(var a, b: char);
begin
if a = b then
exit;
byte(a) := byte(a) xor byte(b);
byte(b) := byte(a) xor byte(b);
byte(a) := byte(a) xor byte(b);
end;
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-==
дык этот обмен имеет несложное продолжение на
циклический сдвиг n переменных:
ззыы: в частности можно любую !ИЗВЕСТНУЮ! (!)
перестановку n чисел реализовать - за n+1 строчку!
Gby! Gby! See you later...
From:
Алексей Ильичёв <alex_z77@mail.ru>
To: sapisoft@yandex.ru
Date: Saturday, March 16, 2002, 6:37:40 AM
Subject: Теоретическая часть: обмен значений
переменных
Здравствуйте, Алексей.
Хотелось бы прокомментировать хитрость, которую
вы продемонстрировали в теоретическом разделе
выпуска 23.
Есть практически аналогичный способ,
обеспечивающий нам полную устойчивость.
Оператор A := A + B; может выполниться с ошибкой, т.к.
никто нам не гарантирует, что размер переменной A
позволяет хранить значение суммы A + B. Чтобы
избежать такого маленького недоразумения, как
переполнение, можно тот же приём проделать через
XOR-сумму. Например так:
A := A xor B; {A = a0 xor b0}
B := A xor B; {B = a0 xor b0 xor b0 = a0}
A := A xor B; {A = a0 xor b0 xor a0 = b0}
Ещё хотелось бы предостеречь читателей от
типичной ошибки:
Procedure Swap(Var A, B : Integer);
begin
A := A xor B;
B := A xor B;
A := A xor B;
end;
Если такой процедурке задать в качестве
параметров одну и ту же переменную, она
обнулиться. Т.к. получится, что A и B - это одна и та
же переменная, а как известно A xor B = 0. То есть если
вы пишите алгоритм, в котором вы не застрахованны
от подобного вызова, лучше не жадничать, и
выделить лишних несколько байт для обмена через
3-ю переменную. (эта ошибка касается так же обмена
через сумму).
Алексей
Шамис: От себя
хочу добавить, что на существование имеет право
любой из представленых алгоритмов, просто каждый
из них имеет те или иные ограничения. Начинающему
легче понять первый вариант решения задачи, а
"продвинутые" программисты могут
использовать функцию XOR для сложения чисел. В
любом случае, спасибо за активность!
ЗАДАЧИ
Последовательность (3
уровень)
Условие:
Дана последовательность натуральных чисел
(значение каждого числа от 1 до 1000).
Последовательность может быть не отсортирована.
Надо найти вариант самой большой (по количеству
элементов) неубывающей последовательности,
составленной из чисел этого ряда. Порядок
включения чисел в неубывающую
последовательность должен соответствовать
порядку следования чисел в первоначальной
последовательности. Иными словами, числа с
большими номерам и в новой последовательности
размещаются правее чисел с меньшими номерами.
Технические
требования:
Файл INPUT.TXT в 1-й строке содержит количество
чисел в последовательности - N (1<=N<=100). Со 2-й
строки и далее указан ряд чисел, каждое число
размещается на новой строке. Поиск ошибок в файле
не требуется, входные данные корректны.
В файле OUTPUT.TXT помещаются выходные данные. 1-я
строка содержит длину максимальной неубыващей
последовательности.
2-я строка и далее - пример такой
последовательности, каждое число в порядке
следования размещается на новой строке.
Пример файлов
входных и выходных данных:
Input.txt
Output.txt
12
59
4
21
36
18
27
79
34
45
47
7
4
21
27
34
45
47
93
Решение: by
Александр Никитин <http://g6prog.narod.ru>:
{$M $8000,0,$4ffff}
Const MaxItem = 100;
TimeLimit = 29*18; {29 sec}
var Numbers, Seq, Best: array[1..MaxItem] of integer;
pc,maxpc,num:integer;
timer:longint absolute $0040:$006C;
jiffy:longint;
Procedure Init;
var i:integer;
begin
jiffy:=timer;
fillchar(Numbers, Sizeof(Numbers),#0);
Seq:=Numbers; Best:=Numbers; pc:=0; maxpc:=0;
assign(input,'seq.in'); reset(input);
readln(num); if num>MaxItem then num:=MaxItem;
for i:=1 to num do readln(Numbers[i]);
close(input);
end;
Procedure Done;
var i:integer;
begin
assign(output,'seq.out'); rewrite(output);
writeln(maxpc);
for i:=1 to maxpc do writeln(Best[i]);
close(output);
end;
procedure StoreChain;
begin
if (pc>maxpc) then begin
Best:=Seq;
maxpc:=pc;
if (maxpc=num) then begin
Done;
Halt(0);
end;
end;
end;
function testFWD(i:integer):integer;
var m:integer;
begin
m:=Numbers[i]; inc(i);
while (i<=num) and (m>Numbers[i]) do inc(i);
if i>num then testFWD:=0 else testFWD:=i;
end;
procedure solution(n:integer); { Основная процедура }
var i,s:integer;
begin
if ((timer-jiffy)>TimeLimit) then exit;
i:=testFWD(n);
if (i=0) then begin
StoreChain;
end else begin
inc(pc); {проверили этот путь}
Seq[pc]:=Numbers[i];
solution(i);
dec(pc); {идем по другому}
s:=Numbers[i]; Numbers[i]:=-1; {вычеркнули}
solution(n);
Numbers[i]:=s; {вернули}
end;
end;
var index:integer;
begin
Init;
index:=1;
repeat
pc:=1;
Seq[pc]:=Numbers[index];
solution(index);
while (index<=num) and (Numbers[index]>=Seq[pc]) do inc(index);
until (index>num);
Done;
end.
ТЕОРИЯ
Немного математики...
Часто на олимпиадах по
информатике предлагаются задачи с
математическим (а точнее с геометрическим
уклоном). Поэтому я решил, что не лишним будет
напомнить читателям некоторые факты, которые
необходимо знать при решении таких задач.
Как известно, любая
прямая задается уравнением вида Y=K*X+B. Так вот.
Следует помнить, что:
- Если две прямые перпендикулярны, то K1*K2=1;
- Если две прямые паралельны, то K1=K2;
Ну, и раз уже заговорили о прямых, то
напомним еще и формулу вычисления координат
середины отрезка:
X = (X1+X2)/2; Y = (Y1+Y2)/2;
Продолжение следует...
Если у вас есть
интересная информация для данной рубрики -
пишите: sapisoft@yandex.ru.
ТЕМЫ ФОРУМА:
2. Петров Денис
[Помогите решить задачку] 15-Мар
(15:56)
Алексей Ильичёв [re:
Помогите решить задачку] 17-Мар
(00:30)
1. Webmaster [Дизайн на сайте] 14-Мар (16:01)
Реклама в рассылке:
Рассылки проекта Sapisoft:
Всегда
рады видеть вас на нашем сайте!
Aleksey Shamis - sapisoft@yandex.ru
Sapisoft Project - http://sapisoft.by.ru