Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
сборник лабораторных работ.doc
Скачиваний:
6
Добавлен:
17.11.2019
Размер:
5.38 Mб
Скачать

Типовые задачи

  1. Перестановка цифр числа Дано целое число. Переставив его цифры в обратном порядке получить новое число. Например, 1234 → 4321.

Нам требуется последовательно получать цифры заданного числа, добавляя их к новому. Цифры числа получаются циклом деления числа на 10 (figure=x%10) с последующим добавлением их к новому числу (y = y*10+figure).

long OldNumber, NewNumber;

char figure;

//получить значение OldNumber:

NewNumber = 0;

while(OldNumber){ //пока есть еще цифры

figure = OldNumber%10; //получить последнюю цифру

NewNumber = NewNumber*10 + figure; //добавить цифру к NewNumber

OldNumber /= 10; //отбросить последнюю цифру

}

Простые вопросы по решению задачи:

  1. Как подсчитать количество цифр числа?

  2. Будет ли данный алгоритм работать, если OldNumber<0?

  1. Поиск делителей числа Найти все делители числа a (0<a<30000).

У числа a гарантированно есть два делителя: 1 и a. Попробуем оценить остальные: самым маленьким из оставшихся является число 2, если 2 – делитель, то частное будет равно a/2, следовательно, a/2 – самый большой возможный делитель. Идея решения проста: перебрать все числа от 2 до a/2, проверить каждое – если нашли делитель, то распечатать.

int a; //исследуемое число

int divisor; //значение делителя

cout << "Введите число: ";

cin>>a;

cout<<"Делители числа "<<a<<" 1, ";//1 – точно делитель

//перебираем возможные делители:

for(divisor=2; divisor<=a/2; divisor++)

//если очередное число – делитель, печатаем его:

if(a%divisor == 0) cout<<divisor<<", ";

cout<<a; //a – точно делитель

Кстати, для представления переменных задачи выбран тип int – целый, диапазон значений типа включает заданный в задаче диапазон для числа a.

Простые вопросы по решению задачи:

  1. Как подсчитать количество делителей числа?

  2. Как проверить, является число простым (делится только на 1 и на себя)?

  1. Разложение на можетели Разложить заданное число на простые множители.

Простые множители числа – простые числа, произведение которых дает заданное число, например: 72 = 2*2*2*3*3.

int val; // исследуемое число

int m; // значение множителя

char n = 0; // количество множителей

for(m=2; m<=val/2; m++){

if(val%m == 0){ // если нашли множитель

cout <<(n ? "*" : "")<< m; // печатаем его

val /= m; // уменьшаем val

m--; // для проверки нескольких одинаковых делителей

n++; // увеличиваем количество найденных делителей

}

}

// последний множитель:

cout<<(n++ ? "*" : "")<< val;

Для решения задачи требуется организовать некоторый повторяющийся процесс, на каждом шаге которого получается очередной множитель. Процесс должен продолжаться пока очередной возможный множитель меньше или равен val/2.

Простой множитель – минимальное простое число, на которое исходное делится без остатка.

Если очередной множитель найден (m), то на следующем шаге цикла его нужно "исключить" из раскладываемого числа, то есть использовать вместо исходного числа val частное от деления его на m (val = val/m).

Число может иметь несколько одинаковых простых множителей, поэтому после того, как множитель найден, нужно вернуться к его проверке еще раз.

Простые вопросы по решению задачи:

  1. Измените решение так, чтобы переменная val могла принимать отрицательные значения.

  1. Поиск простых чисел Найти все простые числа, не превышающие заданное. Простое число – число, которое делится нацело только на 1 и на само себя.

Сущность решения состоит в проверке всех чисел от 2 до заданного числа (val) и выводе их на печать, если они простые. Простое число не делится ни на одно число в диапазоне от 2 до val/2 включительно.

int i; // Номер очередного простого числа

int m; // Очередное проверяемое число

int simple; // Признак, что число простое

int k; // Очередной возможный делитель числа

for(i=0, m=2; m<val; m++){ // Проверяем числа от 2 до val

// Проверяем, является ли число простым:

for(simple=1; k=2; k<=m/2; k++)

if(m%k == 0){

simple=0;

break;

}

if(simple) cout<<m<<" "; // Если m проcтое, то печатаем

}

Замечание: для проверки числа на то, что оно простое, мы проверяли, что оно не делится ни на одно число в диапазоне от 2 до m/2 включительно. Можно также использовать другую проверку – что оно не делится ни на одно простое число от 2 до m/2 включительно. Для этого можно накапливать предыдущими шагами цикла простые числа например в массиве, и проверять очередное число на делимость этих чисел.

Простые вопросы по решению задачи:

  1. Как найти произведение простых чисел, не превышающих заданное?

  2. Как найти количество простых чисел, не превышающих заданное?

  3. Как найти n простых чисел?

  1. Наибольший общий делитель (НОД), НОК Найти наибольший общий делитель двух чисел.

Наибольший общий делитель (НОД) двух чисел – наибольшее число, на которое делятся без остатка оба числа. Поиск НОД можно производить классическим способом поиска чего-либо – простым перебором возможных значений. Но это непроизводительный метод. Воспользуемся алгоритмом Евклида для поиска НОД.

Евклид, самый влиятельный математик всех времен и народов, описал его в одной из книг его знаменитых «Начал» (книги (13 томов), наибольшее число раз изданной и более всего изучавшейся в истории Западного мира (после Библии, конечно)). Алгоритм был известен в древнегреческой математике, по крайней мере, за век до Евклида под названием «антифайресис» – «последовательное взаимное вычитание».

Идея поиска НОД(a, b) состоит в следующем:

  • Если числа a и b равны, то НОД(a, b)=a,

  • Если a>b, то НОД(a, b)= НОД(a-b, b), иначе НОД(a, b)= НОД(b, b-a) (т.е. "заменить большее число на разность")

Пример: НОД(32, 18) = НОД(14, 18) = НОД(14, 4) = НОД(10, 4) = НОД(6, 4)= НОД(2, 4) = НОД(2, 2)= 2

while(a!=b){

if(a>b) a -= b;

else b -= a;

}

// a - НОД

Чаще используется другая интерпретация с использованием остатков от деления:

  • Пусть даны два числа a и b ; a і 0, b і 0, считаем, что a > b. Алгоритм:

  • Если b = 0 , то НОД=а

  • Заменить а на b, b на остаток от деления а на b

Пример: НОД(32, 18) = НОД(18, 14) = НОД(4, 2) = НОД(2, 0)

Формулировка чуть длиннее, но результат получили быстрее.

while(a!=0 && b!=0){

if(a>=b) a=a%b;

else b=b%a;

}

// a+b - НОД

Часто требуется решить похожую задачу – найти наименьшее общее кратное чисел (НОК) – наименьшее число, которое делится на оба числа. Для поиска НОК используется соотношение:

НОК(a , b) = a*b / НОД(a, b).

Простые вопросы по решению задачи:

  1. Как найти НОД нескольких чисел? (замечание: НОД(a,b,c)=НОД(НОД(a,b),c))

  2. Как найти наименьшее общее кратное 5 чисел?

  1. Поиск чисел с заданными свойствами Найти все трехзначные числа, равные кубу суммы своих цифр. Например 512 = (5+1+2)3=83

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

int a,n,k,s;

// диапазон проверки – трехзначные число от 100 до 999:

for(a=100; a<1000; a++){

//поиск суммы цифр:

for(n=a, s=0; n!=0; n=n/10){

k=n%10;

s=s+k;

}

//проверка условия задачи:

if(a==s*s*s) printf("%d^3=%d\n",s,a);

}

Простые вопросы по решению задачи:

  1. Как подсчитать количество таких чисел?

  2. Как найти числа, равные сумме кубов своих цифр?