Перейти к основному содержимому

Задача 1

Условия задачи

Увы, твой браузер не отображает PDF файлы

Скачать

Сначала базовый ввод вывод:

int main() {
int N;
double x; // используем double тк по условию понадобится точность 10^-15
scanf("%d", &N);
for (int i = 0; i < N; ++i){
scanf("%lf", &x); // считваем в буфер число
printf("%.15g\n", exp(x)); // вызываем функцию экспоненты и сразу выводим ответ
// ^^^^^ выводим как нас попросили по условию для точности, а именно:
// .15 значит до 15 знаков после запятой и g - выводит число как обычный %f если помещается,
// а если нет, то в экспоненциальном виде %e (1.3456e+56)
}
return 0;
}

Осталось по мелочи реализовать exp(x):

double exp(double x) {
if (x < 0) return 1.0 / exp(-x);
...
}

Во первых, помним что xn=1xnx^{-n} = \dfrac{1}{x^n}, так что как только видим отрицательное число просто делим 1 на эту же функцию, но уже с положительным x (минус на минус = плюс) и не паримся с отрицательным иксом.

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

ex=1+x1!+x22!+x33!++xnn!\mathrm{e}^{x} = 1 + \dfrac{x}{1!} + \dfrac{x^2}{2!} + \dfrac{x^3}{3!} + \cdots + \dfrac{x^n}{n!}

Считать до бесконечности мы пока не будем: по условию у нас дана точность , следовательно считать будем то тех пор пока элемент последовательности больше 101510^{-15} (ведь элементы меньше не будут вносить эффект для желаемой точности)

Интуитивно, мы просто в цикле мы будем вычислять элементы последовательности и суммировать их, для вычисления нам надо посчитать степень x и факториал, но такой подход является не очень эффективным.

Заметим, что нам необязательно снуля считать весь элемент, а достаточно предыдущий домжнодить на x и разделить на n. К примеру: x=5,n=3, arr3=xnn!=555123arr_3 = \dfrac{x^n}{n!} = \dfrac{5*5*5}{1*2*3}. Мы хотим посчитать следующий элемент с n=4, и вместо того чтобы считать всё заного мы домнажаем arr4=arr3x/n=55551234arr_4 = arr_3 * x / n = \dfrac{5*5*5*5}{1*2*3*4}. Теперь нам нужно просто реализовать это в коде, причём весьма просто

double exp(double x) {
if (x < 0) return 1 / exp(-x);

int n = 1; // номер текущего элемента
double sum=1, term=1; // сумма элементов, последний элемент последовательности
// мы сразу добавляем первый элемент 1 (см формулу), поэтому сумма 1 и последний элемент 1

while (term > 1e-15) { // пока (последний элемент влияет на точность)
term = term * x / n++; // чтобы считать следующий элемент домнажаем текущий на x и делим на n
// ^^^ в той же строке увеличиваем n (постфиксно, сначение используется старое)
sum += term; // добавляем элемент к общей сумме
}
return sum; // возвращаем сумму
}

И плов готов!

Полный код:

#include <stdio.h>

double exp(double x) {
if (x < 0) return 1 / exp(-x);

double sum = 1,term = 1;
int n = 1;
while (term > 1e-15) {
term = term * x / n++;
sum += term;
}
return sum;
}

int main(void){
int N;
double x;
scanf("%d", &N);
for (int i = 0; i < N; ++i){
scanf("%lf", &x);
printf("%.15g\n", exp(x));
}
return 0;
}