Начнем с формул. Площадь треугольника: S = 1/2*a*b*sin C Отсюда: sin C = 2*S/(a*b); cos C = sqrt(1 - sin^2 C) tg C = sin C / cos C; C = atan(tg C) Теорема косинусов: c = sqrt(a^2 + b^2 - 2*a*b*cos C) Площадь: S = c*h/2; отсюда h = 2*S/c Теорема синусов: a/sin A = b/sin B = c/sin C Отсюда: sin A = a/c*sin C; sin B = b/c*sin C cos A = sqrt(1 - sin^2 A); cos B = sqrt(1 - sin^2 B) tg A = sin A/cos A; A = atan(tg A); tg B = sin B/cos B; B = atan(tg B) Периметр: P = a + b + c Теперь записываем в Паскале singam := 2*S/(a*b); cosgam = sqrt(1 - singam*singam); tangam := singam/cosgam; Gamma := atan(tangam); c := sqrt(a*a + b*b - 2*a*b*cosgam); h := 2*S/c; P := a + b + c; sinalp = a/c*singam; cosalp = sqrt(1 - sinalp*sinalp); tanalp := sinalp/cosalp; Alpha := atan(tanalp); sinbet = b/c*singam; cosbet = sqrt(1 - sinbet*sinbet); tanbet := sinbet/cosbet; Beta := atan(tanbet);
Программа работает неверно: даже на примере из условия вместо 2600 выводится 55*245 = 13475. В программе происходит что-то странное, например, сравниваются элементы последовательности и 8 (зачем?)
Подумаем, как можно было бы решать задачу. - Наивный сохранить все числа в массив и пробежаться по нему в двойном цикле, в псевдокоде это выглядит примерно так: max = 0 for i = 1 to n do for j = 1 to n do if |i - j| >= 8 and max < a[i] * a[j] then max = a[i] * a[j] Это нехорошо и по времени (время выполнения порядка n^2), и по памяти (количество памяти растет с ростом n пропорционально n). - Немного ускоряем: у нас пары i, j и j, i ничем не отличаются, так что будем считать, что j < i. Учитывая условие, что |i - j| >= 8, получаем, что j <= i - 8. Переписываем: max = 0 for i = 9 to n do for j = 1 to i - 8 do if max < a[i] * a[j] then max = a[i] * a[j] Это решение работает в 2 раза быстрее, но этого недостаточно. Памяти тоже слишком много. - Продолжаем ускорять. Пусть i зафиксировано. Мы пытаемся сравнить a[i] * a[j] с max для всех j от 1 до i - 8. Очевидно, произведение будет максимально, если a[j] - максимум среди a[1], a[2], ..., a[i - 8]. Возможное решение: создадим массив из максимумов среди первых k чисел, и будем сравнивать уже с максимумом. maximums[1..n] maximums[1] = a[1] for i = 2 to n do maximums[i] = max(maximums[i - 1], a[i]) max = 0 for i = 9 to n do if max < a[i] * maximums[i - 8] then max = a[i] * maximums[i - 8] Это решение уже работает быстро, но остались проблемы с большим расходом памяти. - Последний рывок. Заметим, что для того, чтобы разобраться с числом под номером i, нам совсем не нужен массив a, а из массива maximums достаточно знать только maximums[i - 8], ..., maximums[i - 1] - 8 чисел. Так что большие массивы не нужны, их можно убрать. Тогда программа будет эффективна и по времени, и по памяти.
У меня максимумы хранятся в массиве maxs[0..7], все номера берутся по модулю 8. В вашей программе это может быть реализовано иначе. Pascal: var i, n, t, max: integer; maxs: array[0..7] of integer; begin read(n); read(t); max := 0; maxs[1] := t; for i := 2 to n do begin read(t); if (i > 8) and (max < t * maxs[i mod 8]) then max := t * maxs[i mod 8]; if t > maxs[(i + 7) mod 8] then maxs[i mod 8] := t else maxs[i mod 8] := maxs[(i + 7) mod 8]; end; write(max); end.
Площадь треугольника: S = 1/2*a*b*sin C
Отсюда: sin C = 2*S/(a*b); cos C = sqrt(1 - sin^2 C)
tg C = sin C / cos C; C = atan(tg C)
Теорема косинусов: c = sqrt(a^2 + b^2 - 2*a*b*cos C)
Площадь: S = c*h/2; отсюда h = 2*S/c
Теорема синусов: a/sin A = b/sin B = c/sin C
Отсюда: sin A = a/c*sin C; sin B = b/c*sin C
cos A = sqrt(1 - sin^2 A); cos B = sqrt(1 - sin^2 B)
tg A = sin A/cos A; A = atan(tg A);
tg B = sin B/cos B; B = atan(tg B)
Периметр: P = a + b + c
Теперь записываем в Паскале
singam := 2*S/(a*b); cosgam = sqrt(1 - singam*singam);
tangam := singam/cosgam; Gamma := atan(tangam);
c := sqrt(a*a + b*b - 2*a*b*cosgam); h := 2*S/c;
P := a + b + c;
sinalp = a/c*singam; cosalp = sqrt(1 - sinalp*sinalp);
tanalp := sinalp/cosalp; Alpha := atan(tanalp);
sinbet = b/c*singam; cosbet = sqrt(1 - sinbet*sinbet);
tanbet := sinbet/cosbet; Beta := atan(tanbet);
Подумаем, как можно было бы решать задачу.
- Наивный сохранить все числа в массив и пробежаться по нему в двойном цикле, в псевдокоде это выглядит примерно так:
max = 0
for i = 1 to n do
for j = 1 to n do
if |i - j| >= 8 and max < a[i] * a[j] then
max = a[i] * a[j]
Это нехорошо и по времени (время выполнения порядка n^2), и по памяти (количество памяти растет с ростом n пропорционально n).
- Немного ускоряем: у нас пары i, j и j, i ничем не отличаются, так что будем считать, что j < i. Учитывая условие, что |i - j| >= 8, получаем, что j <= i - 8. Переписываем:
max = 0
for i = 9 to n do
for j = 1 to i - 8 do
if max < a[i] * a[j] then
max = a[i] * a[j]
Это решение работает в 2 раза быстрее, но этого недостаточно. Памяти тоже слишком много.
- Продолжаем ускорять. Пусть i зафиксировано. Мы пытаемся сравнить a[i] * a[j] с max для всех j от 1 до i - 8. Очевидно, произведение будет максимально, если a[j] - максимум среди a[1], a[2], ..., a[i - 8]. Возможное решение: создадим массив из максимумов среди первых k чисел, и будем сравнивать уже с максимумом.
maximums[1..n]
maximums[1] = a[1]
for i = 2 to n do
maximums[i] = max(maximums[i - 1], a[i])
max = 0
for i = 9 to n do
if max < a[i] * maximums[i - 8] then
max = a[i] * maximums[i - 8]
Это решение уже работает быстро, но остались проблемы с большим расходом памяти.
- Последний рывок. Заметим, что для того, чтобы разобраться с числом под номером i, нам совсем не нужен массив a, а из массива maximums достаточно знать только maximums[i - 8], ..., maximums[i - 1] - 8 чисел. Так что большие массивы не нужны, их можно убрать. Тогда программа будет эффективна и по времени, и по памяти.
У меня максимумы хранятся в массиве maxs[0..7], все номера берутся по модулю 8. В вашей программе это может быть реализовано иначе.
Pascal:
var
i, n, t, max: integer;
maxs: array[0..7] of integer;
begin
read(n);
read(t);
max := 0;
maxs[1] := t;
for i := 2 to n do
begin
read(t);
if (i > 8) and (max < t * maxs[i mod 8]) then
max := t * maxs[i mod 8];
if t > maxs[(i + 7) mod 8] then
maxs[i mod 8] := t
else
maxs[i mod 8] := maxs[(i + 7) mod 8];
end;
write(max);
end.