Замечательные числа | |
Числа и СуперЧисла Смита (ускоренная версия) | Постоянная Капрекара |
Определить, является ли число палиндромом (без преобразования в строку) | Совершенные числа (+ алгоритм ускоренного поиска) |
Числа Армстронга | |
{Эта функция считает сумму цифр числа 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-ное суперчисло Смита} function Super(n: Integer): LongInt; var i, count: Integer; smith: LongInt; Found: Boolean; begin i := 0; count := 0; while i <> n do begin Inc(i); repeat Inc(count); smith := GetSmith(count); Found := IsSmith( GetOneDigits(smith) ); until Found; end; Super := smith end; var X: Integer; begin Write('X = '); ReadLn(X); WriteLn('Smith super number (X) = ', Super(X)); end.Программа, представленная выше, работает очень медленно. Чтобы ускорить ее, немного изменим структуру программы: при нахождении следующего числа Смита не будем пересчитывать все предыдущие, а воспользуемся сразу числом, уже найденным на предыдущей итерации:
{ Как и прежде, функция, суммирующая все цифры числа, переданного ей в качестве параметра } function sum_of_digits(n: longint): integer; var s: integer; begin s := 0; while n <> 0 do begin inc(s, n mod 10); n := n div 10; end; sum_of_digits := s end; { Функция, раскладывающая переданное ей число на простые множители, и находящая сумму цифр всех этих множителей } function Factorization(X: longint): longint; var i, s: word; procedure DivX; begin while (x > 1) and (x mod i = 0) do begin inc(s, sum_of_digits(i)); x := x div i; end; end; begin s := 0; i := 2; DivX; i := 3; while (i < x div 2) do begin DivX; inc(i, 2); end; if x > 1 then inc(s, sum_of_digits(x)); Factorization := s; end; { Функция, проверяющая число на простоту } function isPrime(X: word): boolean; var i: integer; begin isPrime := false; if not odd(x) and (x <> 2) then exit; i := 3; while i <= sqrt(x) do begin if x mod i = 0 then exit; inc(i, 2); end; isPrime := true; end; { Функция IsSmith осуществляет проверку, является ли переданное ей число "числом Смита" } function IsSmith(n: longint): boolean; begin IsSmith := not isprime(n) and (sum_of_digits(n) = Factorization(n)); end; { С помощью функции GetNextSmith, можно получить i-ое число Смита, зная предыдущее, (i - 1)-ое. Очень сильно ускорит программу, поскольку избавляет от необходимости постоянно пересчитывать одни и те же числа ... } function GetNextSmith(prev: longint): longint; var i: longint; begin i := prev; repeat inc(i); until IsSmith(i); GetNextSmith := i; end; { Нахождение Суперчисла Смита под номером N } function Super(n: integer): longint; var i, curr: longint; smith: longint; begin curr := 0; i := 0; smith := 2; repeat repeat inc(i); smith := getnextsmith(smith); until IsSmith(sum_of_digits(smith)); inc(curr); until curr = n; Super := smith; end; var X: Integer; begin write('X = '); readln(X); writeln('Smith super number (X) = ', Super(X)); end.В результате получаем программу, работающую быстрее предыдущей в десятки раз.
Определить, является ли число палиндромом (без его преобразования в строку)
function is_palindrom(x: longint): boolean; var prev, T: longint; begin prev := x; T := 0; while x <> 0 do begin T := T * 10 + (x mod 10); x := x div 10; end; is_palindrom := (prev = T) end;Число Армстронга - такое число из k цифр, для которого сумма k-х степеней его цифр равна самому этому числу, например 153 = 13 + 53 + 33
function Power(n, k: Integer): LongInt; var p: LongInt; i: Word; begin p := 1; for i := 1 to k do p := p * n; Power := p End; function IsArmstrong(n: LongInt): Boolean; var Weight: Array[0 .. 9] Of LongInt; i, j: Integer; s: LongInt; begin i := -1; s := n; while s > 0 do begin Inc(i); Weight[i] := s mod 10; s := s div 10 end; for j := 0 to i do s := s + Power(Weight[j], Succ(i)); IsArmstrong := (s = n) end; procedure GetArmstrongs(n: integer); var Weight: Array[0 .. 9] Of LongInt; k, x, min, max, s, p: LongInt; begin for k := 0 to 9 do Weight[k] := Power(k, n); min := Power(10, Pred(n)); max := Pred(10 * min); for x := min to max do begin p := x; s := 0; for k := 1 to n do begin Inc(s, Weight[p mod 10]); p := p div 10 end; if s = x then WriteLn(x, ' - Armstrong') end end; var n: 1 .. 9; begin repeat Write('n [1 .. 9] = '); ReadLn(n) until n In [1 .. 9]; GetArmstrongs(n); WriteLn('1741725: ', isArmstrong(1741725)) end.Выберите любое четырехзначное число, в котором не все цифры одинаковые. Расположите цифры сначала в порядке убывания, затем, переставив их в обратном порядке, образуйте новое число. Вычтите новое число из старого. Повторяя этот процесс с получающимися разностями (не более чем за семь шагов) получим число 6174, которое будет затем воспроизводить самого себя.
function Justify(s: String; Const n: Byte): String; begin while Length(s) < n do s := '0' + s; Justify := s end; function Trim(s: String): String; begin while s[1] = '0' do Delete(s, 1, 1); Trim := s end; function sort_digits(n: Integer; size: Byte): Integer; var s: String; procedure SwapIndex(i, j: Byte); var Ch: Char; begin Ch := s[i]; s[i] := s[j]; s[j] := Ch end; var i, j: Byte; Err: Word; begin Str(n, s); s := Justify(s, size); for i := 1 to size do for j := size downto i+1 do if s[Pred(j)] < s[j] then SwapIndex(Pred(j), j); s := Trim(s); Val(s, n, Err); sort_digits := n end; function revert(n: Integer; size: Byte): Integer; var s, inv: String; i, Err: Word; begin s := Justify(s, size); inv := ''; for i := Length(s) downto 1 do inv := inv + s[i]; s := Trim(s); Val(inv, n, Err); revert := n end; const sz = 4; var res, sort, x: Integer; count: Word; begin Write('Введите 4-х значное число: '); ReadLn(res); count := 0; repeat Inc(count); x := res; sort := sort_digits(x, sz); res := Abs(sort - revert(sort, sz)) until res = x; WriteLn('Const = ', res:(sz+1), ' (', count, ' итераций)') end.Сушествует особый класс чисел, равных сумме всех своих делителей, отличных от самого числа. То есть,
6 = 1 + 2 + 3 28 = 1 + 2 + 4 + 7 + 14и так далее...
const final = 500000; var i, s, divider: longint; begin for i := 2 to final do begin s := 1; for divider := 2 to trunc(sqrt(i)) do begin if i mod divider = 0 then s := s + divider + (i div divider); end; if i = s then writeln(s); end; end., которая выдаст все совершенные числа на промежутке [2 .. final], но эта программа будет довольно долго работать (тем дольше, чем шире просматриваемый интервал).
var i, n, s: longint; divider: integer; bin, bs: integer; { Счетчики для работы со строками } bin_s: string; { Строковое представление Совершенного числа в двоичном виде } check: LongInt; { Число - кандидат на роль Совершенного } begin { Проверит все числа, двоичная запись которых содержит 3 .. 29 символов } for bin := 1 to 14 do begin bin_s := ''; { Создаем бинарное представление числа-кандидата на роль Совершенного } for bs := 1 to bin do bin_s := '1' + bin_s + '0'; bin_s := '1' + bin_s; { Переводим его из 2 представления в десятичное } check := 0; for i := 1 to length(bin_s) do check:= check * 2 + (ord(bin_s[i]) - ord('0')); { ... а теперь - проверяем ТОЛЬКО его, пропуская сотни тысяч чисел, проверка которых заведомо не приведет к успеху (здесь еще тоже можно пооптимизировать, но результат и так выдается практически мгновенно) } s := 1; for divider := 2 to trunc(sqrt(check)) do begin if check mod divider = 0 then s := s + divider + (check div divider); end; if check = s then WriteLn(check); end; end.