Thứ Bảy, 16 tháng 11, 2013

Một vài bài toán đơn giản 2.

Cho công thức sau đây
\[Aver = \sum\limits_{i = 0}^{n - 1} {{{({a_i} - Max)}^2} + } \sum\limits_{i = 0}^{n - 1} {{{({a_i} - Min)}^2} + } \frac{n}{2}{(Max - Min)^2}\]
Hãy viết chương trình tích công thức trên bằng 1 vòng lặp. (không sử dụng mảng)

Khó khăn: Bạn tự hỏi, làm cách nào ta có thể làm được việc ấy với một vòng lặp? Lí do vì trong lúc đọc dữ liệu ta không thể biết Max cũng như Min để sử dụng tính toán, điều mà ta chỉ có thể biết được sau khi đọc xong dữ liệu.
Giải quyết: Vậy hãy tìm cách biến đổi công thức trên sao cho Max và Min không chỉ liên hệ riêng biệt với từng phần tử ${{a_i}}$ mà liên hệ với những biểu thức mà ta có thể tính riêng biệt mà không phụ thuộc vào Max hay Min.
$\begin{array}{l}
^2\\
Aver = 2*\sum\limits_{i = 0}^{n - 1} {a_i^2}  - 2*\sum\limits_{i = 0}^{n - 1} {{a_i}} *(Max + Min) + n*(Ma{x^2} + Mi{n^2}) + \frac{n}{2}{(Max - Min)^2}
\end{array}$
Với công thức trên ta hoàn toàn có thể tính riêng tổng bình phương, tổng của các số, và cuối cùng tổng hợp lại để ra kết quả.

Source code

#include <stdio.h>

using namespace std;

int main()
{
    int n;
    double sum, Min, Max, Ret;
    sum = 0;
    Min = 1e20;
    Max = -Min;
   
    scanf("%d", &n);
    for (int i = 0; i < n; ++i)
    {
        double a;
        scanf("%lf", &a);
        if (a > Max) Max = a;
        if (a < Min) Min = a;
        sum += a;
        Ret += 2*a*a;
    }  
    Ret = Ret - 2*sum*(Max + Min) + n*(Max*Max + Min*Min) + n/2*(Max-Min)*(Max-Min);
   
    printf("%.6lf", Ret);
   
    char u;
    scanf("%c",&u);
    return 0;
}

Không có nhận xét nào:

Đăng nhận xét