Вход


Главная страница >> Учебный процесс >> Задачник >> Олимпиадные задачи (с решениями) >> Разное >> Номер 9

[Назад]    [Содержание ]    [Вперед]

  


Номер 9


  Условие: Номер 9


Задача 8. Ввести три числа а,b,с. 1). Представить a в виде суммы минимального числа целых слагаемых x[i], каждое из которых лежит на отрезке [b,c]. 2). Можно ли представить число а таким образом, чтобы , где b<=x[i]<=c, х[i], а, в, с - целые. Лучшим считается алгоритм находящий такое представление с наименьшим числом множителей. Предусмотреть вариант, когда такого представления не существует.

  Решение задачи: Номер 9


Решение задачи 8. Рассмотрим сначала случай, когда a, b, c, xi - натуральные. 1) Разбивка на слагаемые. Если a<c, то задача неразрешима, если a лежит на [c,d], то задача решена. Пусть a>d. Минимальное число слагаемых будет тогда, когда каждое из слагаемых будет как можно больше. Введем функцию ceil(x)=k+1, если k<x<=k+1, k - целое. Покажем, что в случае, если разложение существует, то необходимо ceil(a/d) слагаемых. Пусть k=ceil(a/d). Если мы возьмем k слагаемых по d, то превышение над a будет p=k*d-a. Каждое из k слагаемых мы можем уменьшить не более чем на d-c. Количество уменьшаемых слагаемых должно быть n=ceil(p/(d-c)). Если n>k, то разложения не существует (слагаемых, которые надо уменьшить, больше, чем у нас есть, другими словами, a div c = a div d, и a mod c <> 0, a mod d <> 0). Если n<=k, то L, L=p div (d-c), слагаемых уменьшаем на (d-c), одно слагаемое - на p mod (d-c), остальные остаются без изменений (равными максимальному). Если a, b, c, xi - целые, то алгоритм практически не изменяется. 2) Разбивка на сомножители. Метод решения этой задачи аналогичен использованному при решении задачи о нахождении максимальной по длине возрастающей подпоследовательности введенной последовательности (см. задачу 20 главы "Рекуррентные соотношения и динамическое программирование"). Опять будем рассматривать только случай a>d. Обозначим через L упорядоченное по возрастанию множество делителей числа A, лежащих на отрезке [c,d], количество делителей не превышает 2*SQRT(A) (если a=f*g, то f<=SQRT(a), g>=SQRT(a), всего разных f - не более SQRT(a), столько же и разных g). Пусть L1 минимальный элемент из L, a L2- максимальный. В массив S[1..k] занесем по возрастанию все делители числа a (включая и само число a=S[k]), начиная с минимального элемента из L. Из утверждения выше следует, что k<=2*SQRT(A)+1. Будем искать минимальную по длине последовательность элементов массива S, ведущую из множества L в число a=S[k] такую, что каждый последующий элемент последовательности при делении на предыдущий дает частное, принадлежащее множеству L, и нулевой остаток. Заведем массивы B[1..k] и C[1..k]. В B[i] будем заносить индекс последующего элемента в подпоследовательности минимальной длины, ведущей из S[i] в S[k] (B[i]=0, если в a из S[i] попасть невозможно), в C[i] будет храниться число элементов в этой минимальной последовательности (отметим, что мы рассматриваем только такие последовательности, у которых частное от деления последующего члена последовательности на предыдущий принадлежит множеству L, а остаток от деления нулевой). Сначала во все элементы C, кроме последнего, занесем какое-нибудь большое число, например 2*A. Если C[i]=2*A, то будем считать, что последовательности элементов, идущей от S[i] к S[k], пока не обнаружено. После заполнения матриц A и B мы находим минимальную длину цепочки, ведущей из множества L в число a. for i:=1 to k-1 do C[k]:=2*A; {последовательности нет} C[k]:=1; {последовательность из одного элемента A} B[k]:=0; {предыдущего элемента нет} for i:=k-1 downto 1 do for j:=i+1 downto k do if (S[j] div S[i] >=L1) and {частное S[j]/S[i]} (S[j] div S[i] <=L2) and {принадлежит L, и} (S[j] mod S[i] =0) {остаток нулевой} then if C[i]>C[j]+1 {если длина обнаруженной} then begin {сейчас подпоследовательности,} {идущей от S[i] к S[k], меньше, чем} C[i]:=C[j]+1; {ранее найденная, то кор ректируем длину и индекс следующего элемента} B[i]:=j end; i:=1; min:=2*A; j:=0; while S[i]<=L2 do begin if C[i]< min then begin min:=C[i]; {корректируем минимум} j:=i; {сохраняем индекс первого элемента} end; i:=i+1 end; if j=0 then writeln('Разложения не существует') else begin writeln('Разложение:'); write(A[j]); for i:=1 to min-1 do begin P:=j; j:=B[j]; write(A[j]/A[p]) {распечатка сомножителя} end end В случае, если a, c, d, xi - целые, в массив S помещаем в порядке возрастания модуля все делители числа A, начиная с минимального элемента в L. Далее - аналогично.

Назад



[Назад]    [Содержание ]    [Вперед]

  


  
За содержание страницы отвечает Гончарова М.Н.
©
Кафедра СПиКБ, 2002-2017