Помощь - Поиск - Пользователи - Календарь
Полная версия: Числа Смита
Форум «Всё о Паскале» > Pascal, Object Pascal > Задачи
Sith
Есть такая задача:
Цитата
Составное число называется числом Смита, если сумма его цифр равна сумме цифр всех чисел, образующихся разложением исходного числа на простые множители. Найти число Смита с номером N

В FAQ лежит задача, но там на Супер числа Смита. Помогите, плз, реализовать эту задачу на Паскале, т.к. с Паскалем пока только начал разбираться, а задачу уже сдавать надо sad.gif
volvo
Цитата
В FAQ лежит задача, но там на Супер числа Смита.
Не только... Просто числа Смита там тоже ищутся, см.
function GetSmith(n: Integer): LongInt;
Гость
Т.е. вот эта часть:
{
	Функция для подсчета суммы цифр числа N
}
function GetOneDigits(n: LongInt): Integer;
var s: Integer;
begin
	s := 0;
	while n <> 0 do begin
		Inc(s, n mod 10);
		n := n div 10;
	end;
	GetOneDigits := s
end;

{
	Эта функция считает сумму цифр разложения исходного числа N
	на простые множители и возвращает в Amount число простых множителей
}
function GetSimpleDigits(n: LongInt; var amount: Integer): Integer;
var
	s, factor: Integer;
begin
	s := 0; factor := 2;
	amount := 0;
	repeat
		if n mod factor = 0 then begin
			s := s + GetOneDigits(factor); Inc(amount);
			n := n div factor
		end
		else Inc(factor)
	until n = 1;
	GetSimpleDigits := s
end;

{
	Функция возвращает N-ное число Смита
}
function GetSmith(n: Integer): LongInt;
var
	i, amount: Integer; od, sd: Integer;
	count: LongInt;
	Found: Boolean;
begin
	i := 0; count := 2;
	while i <> n do begin
		repeat
			Inc(count);
			Found :=
				(GetOneDigits(count) = GetSimpleDigits(count, amount))
				and
				(amount > 1)
		until Found;
		Inc(i)
	end;
	GetSmith := Count
end;

{
	Функция проверяет, является ли N числом Смита
}
function IsSmith(n: LongInt): Boolean;
var
	i: Integer;
	next: LongInt;
begin
	i := 0;
	repeat
		Inc(i); next := GetSmith(i)
	until next >= n;
	IsSmith := (next = n)
end;


А как тогда сделать, чтобы находилось число с номером N, как просят в условии задачи?
volvo
Ну, наверное
n := ... { <-- это номер числа Смита, который будем искать }
Writeln(GetSmith(n));
Гость
А по-проще решения нет?( Мне ее уже завтра сдавать, а я не понимаю половину кода sad.gif(
volvo
Ну, сделай попроще - будет...

Что именно непонятно?
Гость
Ну например как нас учили писать проги на Паскале, это сначала прописываешь в var все переменные, потом уже сам код проги. А тут варов несколько. Плюс, как сделать чтобы он по запросу N числа (номера) выдавал соответствующее число Смита?
volvo
По многочисленным просьбам телезрителей... Брррр.... автора темы публикую реализацию данной задачи без подпрограмм:


var
  n: integer;
  i, candidate, buffer, T: integer;
  s, s_digits, amount, factor: integer;
begin
  { Вводим номер искомого числа Смита }
  write('n = '); readln(n);

  {
    В переменной Candidate будет храниться проверяемое на данный момент число,
    в конечном итоге она будет содержать N-ое число Смита
  }
  candidate := 2;

  { Проходим в цикле, чтобы пропустить N-1 первых, не нужных нам, чисел Смита }
  for i := 0 to n - 1 do begin
    repeat

      inc(candidate);

      {
        1 этап: найдем сумму цифр числа Candidate... Для того, чтобы не повредить
        само число, будем работать с его копией - Buffer.

        Алгоритм поиска суммы цифр не должен вызывать сложностей: выделение последней
        цифры посредством "mod 10", суммирование этих последних цифр и удаление уже
        просуммированной цифры из числа через "div 10"
      }
      buffer := candidate;

      s_digits := 0;
      while buffer <> 0 do begin
        s_digits := s_digits + (buffer mod 10);
        buffer := buffer div 10;
      end;

      {
        Теперь найдем количество (amount) и сумму цифр (s) всех простых множителей
        числа Candidate. Опять предотвращаем порчу числа работой с копией ...
      }
      buffer := candidate;

      amount := 0; s := 0;
      factor := 2; { Factor - это делитель ... }
      repeat
        if buffer mod factor = 0 then begin
          {
            Если остаток от деления числа на фактор = 0, значит Factor - простой множитель числа,
            все что остается - найти его сумму цифр (по алгоритму, описанному выше), увеличить счетчик
            простых множителей, и разделить число-кандидат на Factor, чтобы дальше продолжать
            раскладывать на простые сомножители
          }
          T := factor;
          while T <> 0 do begin

            s := s + (T mod 10);
            T := T div 10;

          end;
          amount := amount + 1;
          buffer := buffer div factor;
        end
        else factor := factor + 1; { <--- Если же число на Factor нацело не делится - увеличиваем делитель}

      {
        Условие окончания цикла разложения на множители - если после очередного шага у нас
        осталась единица. Все, цикл окончен, сумму цифр и количество сомножителей нашли...
      }
      until buffer = 1;

    {
      Если проверенное нами выше число - кандидат все-таки НЕ является числом Смита
      (то есть, условие, записанное ниже НЕ выполняется), то внешний цикл Repeat/Until
      начнется сначала, так будет продолжаться до тех пор, пока ВОТ В ЭТОМ МЕСТЕ
      Candidate не будет являться числом Смита.
    }
    until (s_digits = s) and (amount > 1);

  {
    Сюда попадаем только в случае, когда предыдущее условие истинно, следовательно i-ое
    число Смита мы нашли, ищем следующее или выходим (если найдено уже столько, сколько
    было нужно)
  }
  end;

  writeln(candidate); { <--- Что и требовалось найти... }
end.



Soontir Fel, задавай вопросы на форуме, а не в привате, договорились?
Soontir Fel
Спасибо!!! Просто огромнейшее спасибо за прогу и комментарии, с ними гораздо понятнее что и как!!! Стараюсь быстрее постигать паскаль, чтобы подобного больше не повторялось, и комменты очень помогают!
Ещё раз спасибо!
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.