uzluga.ru
добавить свой файл
1

Ответы

Часть 1

№ задания

1 вариант

2 вариант

А1

4

3

А2

4

3

А3

2

4

А4

2

4

А5

3

2

А6

3

1

А7

1

4

А8

1

4

А9

3

1

А10

2

2

А11

2

1

А12

2

2

А13

4

3



Часть 2

№ задания

1 вариант

2 вариант

В1

30

8

В2

12

11121

В3

19

77

В4

РРРОК

УУУОУ

В5

12

5

В6

-17

72

В7

72

711

В8

18

16

В9

17

23

В10

A120

Б6

В11

62

30

В12

1500

4000

В13

10

8

В14

5

-32

В15

64

11



Часть 3

Вариант 1

С1. Это та же самая задача, что и 26, только переформулированная в соответствии с демо-вариантом ЕГЭ-2012. Сразу замечаем, что в программе else относится к последнему оператору if, то есть в самом деле структура кода такова:

if x <= 1 then

if y >= 1-x then

if y >= x*x then

write('принадлежит')

else write('не принадлежит');

Обратите внимание, что второе условие проверяется в приведенной программе только тогда, когда истинно первое, а третье – только тогда, когда истинны первые два. В остальных ячейках (если условие не проверяется) нужно ставить прочерк:

Обл.

x <= 1

y >= 1-x

y >= x*x

вывод

верно?

A

да

да

нет







B

да

да

да







C

да

нет









D

да

да

нет







E

нет











F

да

нет









G

нет











H

нет











Программы выводит какой-то ответ только тогда когда истинны первые два условия; в этом случае ответ зависит от истинности третьего условия:

Обл.

x <= 1

y >= 1-x

y >= x*x

вывод

верно?

A

да

да

нет

не принадлежит




B

да

да

да

принадлежит




C

да

нет








D

да

да

нет

не принадлежит




E

нет










F

да

нет








G

нет










H

нет










Видим, что верно обрабатываются только областей А и В, для области D выводится неверный ответ (эта область закрашена, но программа выдает ответ «не принадлежит»), а для остальных никакого ответа не выводится.

Обл.

x <= 1

y >= 1-x

y >= x*x

вывод

верно?

A

да

да

нет

не принадлежит

да

B

да

да

да

принадлежит

да

C

да

нет





нет

D

да

да

нет

не принадлежит

нет

E

нет







нет

F

да

нет





нет

G

нет







нет

H

нет







нет

Для исправления программы лучше всего составить новое сложное условие. Выделенная область может быть получена как объединение двух областей: области B выше параболы y >= x*x и линии y = 1-x и (одновременно) слева от прямой x = 1, и верхней части полосы 0<=x<=1, которая снизу ограничена линией y = 1-x:

if ((y >= x*x) and (y >= 1-x) and (x <= 1))

{ синяя область над параболой и прямой }

or

((x >= 0) and (x <= 1) and (y >= 1-x)) { полоса над прямой }

then write('принадлежит')

else write('не принадлежит');

Это условие можно немного упростить, заметив, что условия y >= 1-x и x <= 1 встречаются в условиях для обеих областей:

if (y >= 1-x) and { над прямой }

(x <= 1) and { слева от прямой x = 1}

((y >= x*x) or { выше параболы }

(x >= 0)) { справа от прямой x = 0 }

then write('принадлежит')

else write('не принадлежит');


С2. Эта задача похожа на задачу 23. Здесь нужно найти минимальное из трехзначных чисел, то есть из таких, которые удовлетворяют условию

(100 <= A[i]) and (A[i] < 1000)

В переменную min вначале мы должны записать начальное значение, которое заведомо больше любого трехзначного числа в массиве, например, 1000. Если это значение останется в переменной min после проверки всего массива, это значит, что в массиве нет трехзначных чисел.

^ Решение на естественном языке. Записываем в переменную min начальное значение 1000. В цикле перебираем значения переменной i от 1 до N. Если очередной элемент массива – трехзначное число (больше или равно 100 и меньше 1000) и меньше, чем значение переменной min, записываем значение этого элемента в min. После окончания цикла проверяем значение min: если оно равно 1000, выводим на экран сообщение «Нет таких элементов», иначе выводим значение min.

^ Решение на Паскале.

const N=30;

var A: array [1..N] of integer;

i, min: integer;

begin

for i:=1 to N do readln(A[i]);

min:=1000;

for i:=1 to N do

if (100 <= A[i]) and (A[i] < 1000) and

(A[i] < min) then min := A[i];

if min = 1000 then

writeln('Нет таких элементов')

else writeln(min);

end.


С3. 92

С4. В решении этой задачи можно выделить несколько ключевых моментов:

  1. Выбор удобного способа хранения данных.

  2. Ввод данных и предварительная обработка.

  3. Сортировка в нужном порядке.

  4. Вывод результата.

Информации о каждой ячейке включает ее номер и дату сдачи багажа. Для облегчения расчетов мы сразу представим дату как день от начала года (как это сделать – обсудим после). Эти данные можно объединить в структуру (запись) следующего вида:

type TCell = record no, day: integer; end;

Поле no – это номер ячейки, а поле day – день от начала года, когда в ячейку положен багаж.

Теперь подумаем, как из символьной строки вида '01.06' получить день от начала года. Для этого построим функцию dayFromStart, которая принимает символьную строку такого формата и возвращает целое число – день от начала года:

function dayFromStart(s: sring):integer;

begin

...

end;

В этой функции сначала выделим день и месяц в отдельные переменные d и m, используя стандартную процедуру Val. Номер дня записан в первых двух символах (их можно выделить как Copy(s,1,2)), а номер месяца – в 4 и 5-м символах (Copy(s,4,2)):

Val(Copy(s,1,2), d, i);

Val(Copy(s,4,2), m, i);

Вспомогательная переменная i может быть использована для обнаружения ошибок преобразования, но мы будем считать, что все данные корректны.

Сейчас в переменной d записан номер дня от начала месяца. Чтобы получить номер дня от начала года, нужно добавить к этому значению количество дней во всех предыдущих месяцах, от 1 до m-1:

for i:=1 to m-1 do d:=d+dm[i];

Здесь массив dm содержит количество дней в каждом месяце:

var dm: array[1..12] of integer;

...

dm[1]:=31; dm[2]:=28; dm[3]:=31; dm[4]:=30;

dm[5]:=31; dm[6]:=30; dm[7]:=31; dm[8]:=31;

dm[9]:=30; dm[10]:=31; dm[11]:=30; dm[12]:=31;

Таким образом, функция dayFromStart принимает следующий вид:

function dayFromStart(s: string): integer;

var d, m, i: integer;

begin

Val(Copy(s,1,2), d, i);

Val(Copy(s,4,2), m, i);

for i:=1 to m-1 do d:=d+dm[i];

dayFromStart := d;

end;

Ввод данных. Сначала вводим текущую дату и сразу преобразуем ее в день от начала года (целая переменная curDay):

var curDay: integer;

...

readln(s);

curDay := dayFromStart(s);

Затем вводим количество занятых ячеек

readln(N);

Далее в цикле от 1 до N вводим данные по каждой ячейке, записывая их во вспомогательную переменную c типа TCell:

var c: TCell;

...

read(c.no);

readln(s);

c.day := dayFromStart(s);

Все данные о ячейках, в которых багаж хранится более 3 дней (то есть curDay-c.day>3), нужно записать в отдельный массив (поскольку потом нужно будет их отсортировать!):

var cells: array[1..1000] of TCell;

Чтобы считать количество «отобранных» ячеек, введем счетчик count. Тогда цикл ввода данных будет выглядеть так:

count := 0;

for i:=1 to N do begin

read(c.no);

readln(s); c.day := dayFromStart(s);

if curDay - c.day > 3 then begin

count := count + 1;

cells[count] := c;

end;

end;

После этого сортируем структуры по возрастанию поля day любым методом, например, методом пузырька:

for i:=1 to count-1 do

for j:=count-1 downto 1 do

if cells[j].day > cells[j+1].day then begin

c:=cells[j]; cells[j]:=cells[j+1];

cells[j+1]:=c;

end;

Обратите внимание, что сортировать нужно только первые count структур, а не N! Остается только вывести номера ячеек (поле no каждой структуры):

for i:=1 to count-1 do

writeln(cells[i].no);

Вот полная программа:

type TCell = record

no, day: integer;

end;

var dm: array[1..12] of integer;

s: string;

i, j, N, count, curDay: integer;

c: TCell;

cells: array[1..1000] of TCell;

{ функция для вычисления дня от начала года }

function dayFromStart(s: string): integer;

var d, m, i: integer;

begin

Val(Copy(s,1,2), d, i);

Val(Copy(s,4,2), m, i);

for i:=1 to m-1 do d:=d+dm[i];

dayFromStart := d;

end;

{ основная программа }

begin

dm[1]:=31; dm[2]:=28; dm[3]:=31; dm[4]:=30;

dm[5]:=31; dm[6]:=30; dm[7]:=31; dm[8]:=31;

dm[9]:=30; dm[10]:=31; dm[11]:=30; dm[12]:=31;

readln(s); curDay := dayFromStart(s); { ввод даты }

readln(N); { ввод количества ячеек }

{ ввод данных по всем ячейкам }

count:= 0;

for i:=1 to N do begin

read(c.no);

readln(s); c.day := dayFromStart(s);

if curDay - c.day > 3 then begin

count := count + 1;

cells[count] := c;

end;

end;

{ сортировка по возрастанию поля day }

for i:=1 to count-1 do

for j:=count-1 downto 1 do

if cells[j].day > cells[j+1].day then begin

c:=cells[j]; cells[j]:=cells[j+1];

cells[j+1]:=c;

end;

{ вывод результата }

for i:=1 to count-1 do

writeln(cells[i].no);

end.


Вариант 2

С1 Это та же самая задача, что и 27, только переформулированная в соответствии с демо-вариантом ЕГЭ-2012. Сразу замечаем, что в программе else относится к последнему оператору if, то есть в самом деле структура кода такова:

if x >= 0 then

if y <= 1 then

if (x*x + y*y <= 1) and (y >= x-1)

then

write('принадлежит')

else write('не принадлежит');

Обратите внимание, что второе условие проверяется в приведенной программе только тогда, когда истинно первое, а третье – только тогда, когда истинны первые два. В остальных ячейках (если условие не проверяется) нужно ставить прочерк:

Обл.

x >= 0

y <= 1

(x*x+y*y<=1) and (y>=x-1)

вывод

верно?

A

да

да

да







B

да

да

нет







C

нет











D

нет











E

да

да

нет







F

да

да

нет







G

нет











H

да

нет









J

да

нет









K

нет











Программы выводит какой-то ответ только тогда когда истинны первые два условия; в этом случае ответ зависит от истинности третьего условия:

Обл.

x >= 0

y <= 1

(x*x+y*y<=1) and (y>=x-1)

вывод

верно?

A

да

да

да

принадлежит




B

да

да

нет

не принадлежит




C

нет










D

нет










E

да

да

нет

не принадлежит




F

да

да

нет

не принадлежит




G

нет










H

да

нет








J

да

нет








K

нет










Видим, что верно обрабатываются только областей А и E, для областей B и F выводится неверный ответ (эти области закрашены, но программа выдает ответ «не принадлежит»), а для остальных никакого ответа не выводится.

Обл.

x >= 0

y <= 1

(x*x+y*y<=1) and (y>=x-1)

вывод

верно?

A

да

да

да

принадлежит

да

B

да

да

нет

не принадлежит

нет

C

нет







нет

D

нет







нет

E

да

да

нет

не принадлежит

да

F

да

да

нет

не принадлежит

нет

G

нет







нет

H

да

нет





нет

J

да

нет





нет

K

нет







нет

Для исправления программы лучше всего составить новое сложное условие. Выделенная область может быть получена как объединение двух областей: полукруга

(x >= 0) and (x*x + y*y <= 1)

и треугольника

(x >= 0) and (y <= 1) and (y >= x-1)

Получаем:

if ((x >= 0) and (x*x + y*y <= 1)) { полукруг }

or

((x >= 0) and (y <= 1) and (y >= x-1)) { треугольник }

then write('принадлежит')

else write('не принадлежит');

Это условие можно немного упростить, заметив, что условие x >= 0 встречается в условиях для обеих областей:

if (x >= 0) and

((x*x + y*y <= 1) or

((y <= 1) and (y >= x-1)))

then write('принадлежит')

else write('не принадлежит');


С2. Эта задача в целом напоминает упрощенный вариант предыдущей, поэтому можно сразу привести решение. Единственная тонкость – можно исключить операции с вещественными числами, которые (теоретически) могут привести к ошибкам. Подробно этот прием описан в решении предыдущей задачи.

^ Решение на естественном языке. Записываем в переменную s начальное значение 0. В цикле добавляем все значения элементов массива, от 1-ого до 30-ого, к значению переменной s. После завершения цикла делим значение s на 30, чтобы найти среднее значение. Далее записываем в переменную j начальное значение 0. В цикле рассматриваем все элементы массива, от
1-ого до 30-ого, сравниваем значение текущего элемента со значением переменной s. Если значение текущего элемента больше значения s, увеличиваем счетчик j на 1. После завершения цикла выводим значение переменной j.

В приведенном выше решении на естественном языке дан «чистый» алгоритм. При работе на реальном компьютере нужно заботиться о точности вычислений, поэтому в программе на Паскале вместо проверки условия a[i] > среднего мы используем равносильное ему a[i]*N > суммы элементов. При этом переменную s можно было бы сделать и целой (но она вещественная по условию задачи, это нельзя менять!).

const N=30;

var a: array [1..N] of integer;

i, j: integer;

s: real;

begin

for i:=1 to N do readln(a[i]);

s:= 0;

for i:=1 to N do s:= s + a[i];

j:= 0;

for i:=1 to N do

if a[i]*N > s then j:= j + 1;

writeln(j);

end.


С3. 627

  1. С4. Сложность этой задачи состоит в том, что объем используемой памяти не должен зависеть от длины последовательности чисел. Следовательно, запоминать числа нельзя. Нежелательно хранить и все возможные произведения введенных чисел (их может быть миллион, от 1 до 1000000, поскольку каждое введенное число находится в интервале от 1 до 1000).

Таким образом, массив заводить нельзя. Введем следующие переменные:

x – вспомогательная переменная, в которую читается очередное число

count – счётчик введенных чисел

C0 – контрольное значение

Общая структура программы выглядит так:

count:=0;

readln(x);

while x <> 0 do begin

count:= count + 1;

{ обработка введенного значения x }

readln(x);

end;

readln(C0);

Структура цикла определяется тем, что

  1. до начала цикла нужно ввести первое значение элемента последовательности; если оно равно 0, то цикл выполнять не нужно;

  2. если очередное введенное значение равно нулю, нужно закончить цикл и не обрабатывать его (это не элемент последовательности), поэтому оператор readnl(x) стоит в конце тела цикла;

Заметим, что можно было использовать и цикл с постусловием, но при этом нужен еще условный оператор:

count:=0;

repeat

readln(x);

if x > 0 then begin

count:= count + 1;

{ обработка введенного значения x }

end;

until x = 0;

readln(C0);

Таким образом, главная проблема – обработка введенного значения x так, чтобы в конце цикла мы получили в некоторой переменной (назовем ее C) контрольное значение, и его можно было сравнить с введенным значением C0. По условию контрольное значение – это наибольшее произведение чисел, делящееся на 6.

Сначала предположим, что в этом произведении один из сомножителей делится на 6, тогда второй может быть любым. Наибольшее произведение таких пар может быть найдено следующим образом:

  1. найти наибольшее число, делящееся на 6.

  2. найти наибольшее число, кроме найденного в п. 1 (заметим, что оно также может делиться на 6!!!).

Для поиск наибольшего из вводимых чисел не нужно хранить все числа. Введем две переменные:

max6 – максимальное число, делящееся на 6

max – максимальное из оставшихся чисел

Поскольку все числа больше 0, сначала в эти переменные запишем нули.

Допустим, что очередное число прочитано в переменную x. Тогда поиск max6 и max на очередном шаге цикла выглядит так:

if (x mod 6 = 0) and (x > max6) then

max6:= x

else

if x > max then max:= x;

Теперь рассмотрим еще один вариант: произведение делится на 6, но ни один из сомножителей не делится на 6. Это может быть тогда, когда один сомножитель делится на 2, в второй – на 3. Тогда получается, что нужно среди всех введенных чисел, не делящихся на 6, найти наибольшее, делящееся на 2 (в программе будем хранить его в переменной max2), и наибольшее, делящееся на 3 (переменная max3). Их произведение – второй кандидат на искомый максимум.

Начальные значение max2 и max3 можно также взять нулевыми (все вводимые числа больше нуля). На каждом шаге цикла они могут измениться, для этого используем такой условный оператор:

if x mod 6 <> 0 then begin { если число не делится на 6 }

if (x mod 2 = 0) and (x > max2) then max2:= x;

if (x mod 3 = 0) and (x > max3) then max3:= x;

end;

Можно немного упростить этот оператор, убрав условие «неделимости» на 6. Проблема только в том, чтобы число не попало одновременно в группу «делящихся на 2» и «делящихся на 3». Для этого достаточно использовать else:

if (x mod 2 = 0) and (x > max2) then max2:= x

else

if (x mod 3 = 0) and (x > max3) then max3:= x;

После окончания цикла нужно выбрать максимальное из произведений max6*max и max2*max3, это и будет контрольное значение (переменная C):

if max6*max > max2*max3 then

C:= max6*max

else C:= max2*max3;

Приведем полную программу:

program qq;

var x, count, C, C0, max, max2, max3, max6: integer;

begin

count:=0; max:=0; max2:=0; max3:=0; max6:=0;

readln(x);

while x <> 0 do begin

count:= count + 1;

if (x mod 6 = 0) and (x > max6) then

max6:= x

else if x > max then max:= x;

if (x mod 2 = 0) and (x > max2) then max2:= x

else

if (x mod 3 = 0) and (x > max3) then max3:= x;

readln(x);

end;

readln(C0);

if max6*max > max2*max3 then

C:= max6*max

else C:= max2*max3;

writeln('Получено чисел: ', count);

writeln('Полученное контрольное значение: ', C0);

writeln('Вычисленное контрольное значение: ', C);

if C = C0 then

writeln('Контроль пройден.')

else writeln('Контроль не пройден.');

end.