Тверской государственный университет
Опубликован: 06.10.2013 | Доступ: свободный | Студентов: 1373 / 335 | Длительность: 02:37:00
Специальности: Преподаватель
Лекция 4:

Разбор задач части С

< Лекция 3 || Лекция 4: 1234

Задача С4 (Алгоритмически сложная задача)

В разделе С это вторая задача на программирование. Если задача С2 требует от школьника знания классического алгоритма, то для "красивого" решения задачи С4 требуется придумать нестандартный алгоритм. Приведу вариант задачи, данный на экзамене.

<<

По каналу связи передается последовательность положительных целых чисел, все числа не превышают 1000. Количество чисел известно, но может быть очень велико. Затем передается контрольное значение последовательности – наибольшее число R, удовлетворяющее следующим условиям:

  1. R – произведение двух различных переданных элементов последовательности ("различные" означает, что не рассматриваются квадраты переданных чисел, произведения различных элементов последовательности, равных по величине, допускаются).
  2. R делится на 35.

Если такого числа R нет, то контрольное значение полагается равным 0.

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

Вычисленное контрольное значение: - …

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

Перед текстом программы кратко опишите алгоритм.

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

>>

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

Вычислить R - максимальное произведение двух элементов массива, при условии, что R делится на 35.

Задача формулируется в одну строчку, суть ее сохраняется, но все запутывающие "завитушки" о контрольных значениях, разных элементах устраняются.

У задачи есть элегантное решение, а есть и неэффективное переборное решение. К сожалению, система оценивания решения не совершенна. Школьник, представивший неэффективное переборное решение получит лишь на балл меньше того школьника, который представит элегантное решение, не требующее запоминания всех чисел и перебора всех возможных значений.

Приступим к разбору решения. Рассмотрим оба решения этой задачи. Первое достаточно очевидное. Нужно прочитать все числа, запомнить их в массиве. Тогда задача сводится к известной задаче нахождения максимума в массиве. Нужно найти максимальное произведение двух элементов, удовлетворяющее дополнительным условиям. Для этого достаточно организовать цикл по i и внутренний цикл по j, вычисляя произведение элементов a[i] * a[j], анализируя его на выполнение дополнительного условия и сравнивая с текущим максимальным значением произведения элементов. Приведу текст соответствующей программы на языке С#:

static void Main()
  {
    int N;
    Console.WriteLine("Введите количество элементов массива");
    N = int.Parse(Console.ReadLine( ));
    int[] a = new int[N];
    Console.WriteLine("Введите элементы массива");
    for(int i =0; i <N; i++)
      a[i] = int.Parse(Console.ReadLine());

    int R = 0;
    int cand =0;
    for(int i = 0; i < N; i++)
      for(int j = i+1; j < N; j++)
      {
        cand = a[i] * a[j];
        if (cand % 35 == 0 && cand > R)
          R = cand;
      }
    Console.WriteLine("R = " + R);
  }
    

В таком варианте программа достаточно проста и доступна для школьников, умеющих писать простые программы. Что касается "завитушек", введенных в формулировку данной задачи, то первое требование о "разных" элементах выполняется автоматически, поскольку внутренний цикл начинается со значения i +1, так что квадраты чисел просто не строятся. "Завитушка" насчет контроля значений просто означает, что нужно ввести "контрольное" значение R и сравнить его с вычисленным. Я не стал этого делать, дабы не затенять суть этой простой программы.

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

Давайте рассмотрим эффективный по памяти и быстродействию алгоритм, который не требует запоминания массива и не требует введения внутреннего цикла. Идея алгоритма основана на том, что на разыскиваемое произведение двух элементов накладывается дополнительное условие – произведение должно делиться на 35. Поскольку число 35 имеет только два простых сомножителя, то большинство элементов в массиве можно игнорировать. После небольших размышлений можно понять, что есть два претендента на ответ:

cand1 = max5 * max7;

cand2 = max35 * max.

Здесь:

  • max5 – это максимальный элемент среди тех элементов, которые делятся на 5, но не делятся на 35;
  • max7– это максимальный элемент среди тех элементов, которые делятся на 7, но не делятся на 35;
  • max35 – это максимальный элемент среди элементов, которые делятся на 35;
  • max – это максимальный элемент массива. Учитывая "завитушку" о разных элементах, на max накладывается дополнительное условие, - его индекс не должен совпадать с индексом элемента, представляющего max35

Эти рассуждения позволяют построить эффективную программу, не требующую запоминания чисел в массиве и позволяющую выполнить все основные вычисления за один проход по данным.

Вот как может выглядеть подобная программа, написанная на языке С#:

static void Main(string[] args)
{
  int N;
  Console.WriteLine("Введите количество элементов массива");
  N = int.Parse(Console.ReadLine());
  int item;
  int max, max5, max7, max35;
  int index_max35;
  max = max5 = max7 = max35 = 0;
  index_max35 = 0;
  Console.WriteLine("Введите поочередно элементы массива");
  for (int i = 0; i < N; i++)
    {
      item = int.Parse(Console.ReadLine());
      if (item % 35 == 0 && item > max35)
      {
        max35 = item;
        index_max35 = i;
      }
      else
      {
        if (item % 5 == 0 && item > max5)
          max5 = item;
        if (item % 7 == 0 && item > max7)
          max7 = item;
      }
      if (i != index_max35 && item > max)
        max = item;
    }
    int R,R_Contr, cand1, cand2;
    cand1 = max5 * max7;
    cand2 = max35 * max;
    if (cand1 > cand2)
      R = cand1;
    else
      R = cand2;
    Console.WriteLine("Вычислено значение R = " + R);
    Console.WriteLine("Введите контрольное значение");
    R_Contr = int.Parse(Console.ReadLine());
    if (R == R_Contr)
      Console.WriteLine("Контроль пройден");
    else
      Console.WriteLine("Контроль не пройден");
  }
    

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

Подводя общие итоги экзамена по информатике, можно отметить, что наиболее легкой была задача С3, с которой справилось большинство школьников, представивших свои работы. Многие школьники представили корректное решение задачи С1. С программированием дело обстоит значительно хуже. Сравнительно простая задача С2 для многих оказалась трудной задачей. Совсем плохая ситуация сложилась с задачей С4, но не потому, что не было представлено ее правильных решений. Но об этой ситуации следует сказать особо.

Печальные итоги проверки экзамена по информатике

Я участвовал в работе комиссии по проверке части С экзамена по информатике. Комиссии было представлено более 500 работ. Членам комиссии было известно, что решения задач были выложены в интернете. Доступными были рекомендованные решения, то есть те самые решения, которые представлялись комиссиям, проверяющим работы. Так что вина за утечку информации лежит не на школьниках, а на людях, отвечающих за честное проведение экзамена.

Представьте себе положение членов комиссии, которые видят, что представленное школьником решение буква в букву повторяет рекомендованное решение. У нас нет никаких сомнений, что решение списано, поскольку оно буквально повторяет рекомендованное решение, которое кстати говоря является далеко не идеальным, поскольку включает лишние проверки и довольно запутанным образом проверяет условие, накладываемое на максимальный элемент. Мы знаем, что представлена работа, не заслуживающая какой-либо положительной оценки, которую следует оценить на "неудовлетворительно".

У нас нет права занижать оценку за списывание. Мы видим правильное решение, должны по правилам ставить максимальный балл, понимая, что оценка не заслужена, что лучшие оценки ЕГЭ получают не лучшие ученики, а обманщики.

< Лекция 3 || Лекция 4: 1234
Мария Паршикова
Мария Паршикова
Александр Коротенко
Александр Коротенко
Курс "Подготовка к ЕГЭ по информатике". Знаю, что ответ верный, но система его не принимает. Пытался ввести его в разных формах (строчные, прописные, все, одна и т.д.)