Задаци: Елементарне статистике

Алгоритми и програми у програмском језику C: Елементарне статистике.

Факторијел

Прочитај текст задатка.

За одређивање факторијела природног броја n користимо променљиву faktorijel у којој редом акумулирамо производ бројева од 1 до n.

На почетку вредност променљиве faktorijel поставимо на 1. Након тога, коришћењем петље у којој ћемо бројачкој променљивој i, додељивати редом вредности од 1 до n, у сваком пролазу кроз петљу променљиву faktorijel множити са i.

Предложено решење задатка

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main(void)
{
    int n, f = 1;
    scanf("%d", &n);
    for (int i = 1; i <= n; i++)
        f *= i;
    printf("%d", f);
    return 0;
}

Степен

Прочитај текст задатка.

Резултат можемо добити ако израчунамо производ xxn. Производ серије итеративно можемо израчунати тако што вредност производа иницијализујемо на јединицу, а затим га у сваком кораку петље множимо са наредним елементом серије (у овом случају вредношћу x).

Предложено решење задатка (1)

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main(void)
{
    double x;
    int n, f = 1;
    scanf("%lf%d", &x, &n);
    double s = 1.0;
    for (int i = 0; i < n; i++)
        s *= x;
    printf("%.5lf", s);
    return 0;
}

Већина језика већ пружа готову функцију или операцију степеновања. У језику C степеновање реалних бројева се врши функцијом pow, декларисаној у заглављу math.h.

Предложено решење задатка (2)

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <math.h>

int main(void)
{
    double x;
    int n, f = 1;
    scanf("%lf%d", &x, &n);    
    printf("%.5lf", pow(x, n));
    return 0;
}

Просек свих бројева до краја улаза

Прочитај текст задатка.

Као што смо већ видели, рачунање просека серије бројева своди се на засебно израчунавање збира и броја елемената серије и њихово дељење (ако су и збир и број цели бројеви, пре дељења је потребно конвертовати их у реални тип).

Видели смо и да се збир серије бројева израчунава тако што се променљива у којој се акумулира збир иницијализује на нулу, а затим се у петљи пролази кроз елементе серије и збир се увећава за текући елемент.

Видели смо и да се број елемената серије одређује тако што се бројачка променљива у којој се тај број акумулира иницијализује на нулу, а затим се у петљи пролази кроз елементе серије и бројач се у сваком кораку увећава за један.

Показано је и како се може организовати петља која учитава све бројеве са стандардног улаза.

Предложено решење задатка

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main(void)
{
    int z = 0, i = 0, n;
    while (scanf("%d", &n) != EOF)
    {
        z += n;
        i++;
    }
    double p = (double)z / (double)i;
    printf("%.5lf", p);
    return 0;
}

Средине

Прочитај текст задатка.

Просечна брзина представља однос укупног пређеног пута и укупног времена трајања пута.

Претпоставимо да је сваки део пута трајао исто време t (у сатима). Тада је на првом делу пута аутомобил прешао v1t километара, на другом v2t километара, и тако даље, док је на последњем делу прешао vnt километара. Дакле, укупан пређени пут је (v1+v2++vn)t километара. Укупно време је nt сати. Зато је просечна брзина једнака (v1+v2++vn)tnt=v1+v2++vnn.

Претпоставимо сада да је на сваком делу пута аутомобил прешао исто растојање s (у километрима). Тада се на првом делу пута кретао sv1 сати, на другом sv2 сати и тако даље, све до последњег дела где се кретао svn сати. Дакле, укупни пређени пут је ns, док је укупно време једнако sv1+sv2++svn. Дакле, просечна брзина једнака је snsv1+sv2++svn=n1v1+1v2++1vn.

Приметимо да се у првом случају просечна брзина израчунава као аритметичка средина појединачних брзина, док се у другом случају израчунава као хармонијска средина појединачних брзина.

Израчунавање аритметичке средине (просечне вредности) свих бројева учитаних са стандардног улаза приказали смо раније. У овом случају радимо са реалним бројевима, па је имплементација још једноставнија јер не морамо да водимо рачуна о конверзији типова. Што се тиче израчунавања хармонијске средине, она се може израчунати тако што се израчуна збир реципрочних вредности свих брзина, а затим се n подели тим бројем. Збир реципрочних вредности се рачуна тако што се на променљиву коју иницијализујемо на нулу у петљи додају једна по једна реципрочна вредност.

Предложено решење задатка

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main(void)
{
    int i = 0;
    double x, z = 0.0, zr = 0.0;
    while (scanf("%lf", &x) != EOF)
    {
        i++;
        z += x;
        zr += 1.0 / x;
    }
    double as = z / i;
    double hs = i / zr;
    printf("%.2lf\n%.2lf", as, hs);
    return 0;
}

Просечан раст цена

Прочитај текст задатка.

Претпоставимо да је основна цена производа C. Тада је цена након првог месеца једнака C(1+p1100), након два месеца једнака C(1+p1100)(1+p2100) и тако даље, да би на крају n месеци била једнака C(1+p1100)(1+p2100)(1+pn100). Ако би пораст цене у сваком месецу било p тада би цена након n месеци била једнака C(1+p100)n. Пошто желимо да овако израчунате коначне цене буду једнаке, тј. да важи C(1+p1100)(1+pn100)=C(1+p100)n, p се може израчунати као p=100((1+p1100)(1+pn100)n1).

n-ти корен из производа n бројева назива се геометријска средина.

Производ серије можемо израчунати алгоритмом у коме резултат иницијализујемо на 1 и множимо га редом једним по једним кофицијентом повећања 1+p100.

Корен можемо израчунати свођењем на степеновање xn=x1n и применом функције pow

Предложено решење задатка

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <math.h>

int main(void)
{
    int n;
    double x, p = 1.0;
    scanf("%d", &n);
    for (int i = 0; i < n; i++)
    {
        scanf("%lf", &x);
        p *= (1.0 + x / 100.0);
    }
    double pp = 100.0 * (pow(p, 1.0 / n) - 1.0);
    printf("%.2lf", pp);
    return 0;
}

Производња малина

Прочитај текст задатка.

Производња сваког месеца чини геометриски низ тј. геометријску прогресију (низ бројева у коме је количник сваког члана и њему претходног константан) и у овом задатку потребно је одредити његов n-ти члан.

Маринко прве године планира да произведе t тона малина. Друге године планира за p% више тона него прве године. Значи друге године планира да произведе t(1+p100) тона. Слично, треће године за p% више тона него друге године, односно t(1+p100)(1+p100) што износи t(1+p100)2 тона. Закључујемо да за последњу годину, n-тy годину, планира производњу t(1+p100)n1 тона.

У језику C степен броја се може израчунати функцијом pow декларисаном у заглављу math.h.

Предложено решење задатка (1)

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <math.h>

int main(void)
{
    int n;
    double t, p;
    scanf("%d%lf%lf", &n, &t, &p);
    double x = t * pow(1 + p / 100, n - 1); 
    printf("%.2lf", x);
    return 0;
}

Задатак може бити решен и уз помоћ петље у којој се производ иницијализује на вредност t и у сваком од n корака се множи са 1+p100 (израчунава се производ серије), али тиме би се добило ружније и неефикасније решење.

Предложено решење задатка (2)

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main(void)
{
    int n;
    double t, p;
    scanf("%d%lf%lf", &n, &t, &p);
    double x = t;
    for (int i = 1; i < n; i++)
        x = x * (1 + p / 100);
    printf("%.2lf", x);
    return 0;
}

Сума низа бројева

Прочитај текст задатка.

Обележимо са a1,a2,,an бројеве које треба да саберемо. Oни представљају геометријски низ (у коме је количник свака два суседна броја исти) и тражена вредност је сума првих n чланова тог низа.

Једноставном анализом можемо закључити да је ai=aqi1 за 1in. Задатак је одредити суму a1+a2++an1+an. Обележимо тражену суму са S. Применом формуле за ai добијамо да је

S=a+aq1+aq2++aqn2+aqn1

Ако леву и десну страну претходне једнакости помножимо са 1q (напоменимо 1q0) добијамо једнакост:

S(1q)=a(1q)+aq(1q)+aq2(1q)++aqn2(1q)+aqn1(1q)

Извршимо множења на десној страни једнакости:

S(1q)=aaq+aqaq2+aq2aq3++aqn2aqn1+aqn1aqn

Сређивањем последњег израза добијамо S(1q)=aaqn. Према томе

S=a1qn1q

У језику C степен броја се може израчунати функцијом pow декларисаном у заглављу math.h.

Предложено решење задатка (1)

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <math.h>

int main(void)
{
    int n;
    double a, q;
    scanf("%d%lf%lf", &n, &a, &q);
    double s = a * (1 - pow(q, n)) / (1 - q);
    printf("%.5lf", s);
    return 0;
}

Рецимо и да је збир било могуће одредити и тако што бисмо употребили алгоритам сабирања елемената серије коришћењем петље, при чему бисмо сваки наредни елемент могли инкрементално израчунати од претходног множењем са q.

Предложено решење задатка (2)

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main(void)
{
    int n;
    double a, q;
    scanf("%d%lf%lf", &n, &a, &q);
    double x = a;
    double s = a;
    for (int i = 1; i < n; i++)
    {
        x *= q;
        s += x;
    }
    printf("%.5lf", s);
    return 0;
}

Једнакост растојања

Прочитај текст задатка.

Тражена тачка је аритметичка средина унетих тачака.

Докажимо претходно тврђење. Ако са x означимо тражену тачку тада, за низ тачака xi, i=1,,n, важи:

i=1xixn(xxi)=i=1xi>xn(xix)

Ако се израз са десне стране пребаци на леву и када знак уђе у другу суму добија се:

i=1xixn(xxi)+i=1xi>xn(xxi)=0

што је еквивалентно са

i=1n(xxi)=0

Одавде се добија:

i=1nx=nx=i=1nxi

Према томе, тражена тачка је аритметичка средина унетих тачака:

x=i=1nxin

Израчунавање аритметичке средине серије бројева већ смо разматрали раније. Потребно је израчунати збир елемената серије и затим га поделити са бројем елемената серије (који је у овом случају унапред познат).

Предложено решење задатка

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main(void)
{
    int n;
    scanf("%d", &n);
    double s = 0, x;
    for (int i = 0; i < n; i++)
    {
        scanf("%lf", &x);
        s += x;
    }
    printf("%.5lf", s / n);
    return 0;
}

Тежиште

Прочитај текст задатка.

Већ смо разматрали тежиште скупа тачака на правој које је одређено као просечна вредност координата тачака. Исто ће се догодити и код тачака у равни. Заиста, обележимо тежиште са T, а тачке са A1,,An, a са OT=(Tx,Ty), OA1=(A1x,A1y), …, OAn=(Anx,Any) векторе њихових координата. Кренимо од услова да је A1T++AnT=0. У последњој једнакости додамо на обе стране OA1+OA2++OAn и добијамо nOT=OA1+OA2++OAn, односно OT=OA1+OA2++OAnn.

Одатле следи:

Tx=A1x+A2x++Anxn
Ty=A1y+A2y++Anyn

Задатак се решава једноставним израчунавањем аритметичких средина координата x и координата y датих тачака.

Предложено решење задатка

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main(void)
{
    int n;
    scanf("%d", &n);
    double zx = 0.0, zy = 0.0, x, y;
    for (int i = 0; i < n; i++)
    {
        scanf("%lf%lf", &x, &y);
        zx += x;
        zy += y;
    }
    double tx = zx / n;
    double ty = zy / n;
    printf("%.5lf\n%.5lf", tx, ty);
    return 0;
}