1. 程式人生 > 其它 >1104 Sum of Number Segments (20 分)(數學問題)

1104 Sum of Number Segments (20 分)(數學問題)

Given a sequence of positive numbers, a segment is defined to be a consecutive subsequence. For example, given the sequence {0.1, 0.2, 0.3, 0.4}, we have 10 segments: (0.1) (0.1, 0.2) (0.1, 0.2, 0.3) (0.1, 0.2, 0.3, 0.4) (0.2) (0.2, 0.3) (0.2, 0.3, 0.4) (0.3) (0.3, 0.4) (0.4).

Now given a sequence, you are supposed to find the sum of all the numbers in all the segments. For the previous example, the sum of all the 10 segments is 0.1 + 0.3 + 0.6 + 1.0 + 0.2 + 0.5 + 0.9 + 0.3 + 0.7 + 0.4 = 5.0.

Input Specification:

Each input file contains one test case. For each case, the first line gives a positive integer N, the size of the sequence which is no more than 105. The next line contains N positive numbers in the sequence, each no more than 1.0, separated by a space.

Output Specification:

For each test case, print in one line the sum of all the numbers in all the segments, accurate up to 2 decimal places.

Sample Input:

4
0.1 0.2 0.3 0.4

Sample Output:

5.00

題目大意:

給定一個正數數列,我們可以從中擷取任意的連續的幾個數,稱為片段。例如,給定數列{0.1, 0.2, 0.3, 0.4},我們有(0.1) (0.1, 0.2) (0.1, 0.2, 0.3) (0.1, 0.2, 0.3, 0.4) (0.2) (0.2, 0.3) (0.2, 0.3, 0.4) (0.3) (0.3, 0.4) (0.4) 這10個片段。給定正整數數列,求出全部片段包含的所有的數之和。如本例中10個片段總和是0.1 + 0.3 + 0.6 + 1.0 + 0.2 + 0.5 + 0.9 + 0.3 + 0.7 + 0.4 = 5.0,在一行中輸出該序列所有片段包含的數之和,精確到小數點後2位~

分析:

將數列中的每個數字讀取到temp中,假設我們選取的片段中包括temp,且這個片段的首尾指標分別為p和q,那麼對於p,有i種選擇,即12…i,對於q,有n-i+1種選擇,即i, i+1, … n,所以p和q組合形成的首尾片段有i * (n-i+1)種,因為每個裡面都會出現temp,所以temp引起的總和為temp * i * (n – i + 1);遍歷完所有數字,將每個temp引起的總和都累加到sum中,最後輸出sum的值~

【Update 2020-6-18】PS:

題目更新了測試樣例,導致之前的程式碼測試點2(第3個測試點)無法通過,研究到凌晨四點找錯誤原因…後來找到了給PAT這道題提反饋改測試用例的這位同學寫的關於這道題的部落格:https://blog.zhengrh.com/post/about-double/
感謝他讓我找到了錯誤的原因,大概意思是:N比較大時,double型別的值多次累加導致的精度誤差,因為輸入為十進位制小數,儲存到double中時,計算機內部使用二進位制表示,且計算機的字長有限,有的十進位制浮點數使用二進位制無法精確表示只能無限接近,在字長的限制下不可避免會產生舍入誤差,這些細微的誤差在N較大時多次累加會產生較大誤差,所以建議不要使用double型別進行多次累加的精確計算,而是轉為能夠精確儲存的整型。嘗試把輸入的double型別的值擴大1000倍後轉為long long整型累加,同時使用long long型別儲存sum的值,輸出時除以1000.0轉為浮點型再輸出(相當於把小數點向後移動3位後再計算,避免double型別的小數部分儲存不精確,多次累加後對結果產生影響)
但我覺得乘以1000也未必嚴謹,可能測試樣例最小隻有小數點後三位,如果測試樣例變成小數點後四位、五位、六位,乘以1000相當於直接在小數點後三位處截斷,而原本第四五六位經過多次累加進位後依然可能會引起精度問題,但如果乘以10000就會超出long long的值,我認為最精確的應該是擷取到所有小數中最大的位數的那一位。。可能我的想法有疏漏,經過測試,測試樣例確實沒有超過小數點後三位,雖然修改為乘以1000後代碼已經AC,但如果對測試樣例稍加修改,可能又會導致不AC了…所以這道題先打個問號吧,我猜可能將來題目樣例還會被修改…

原文連結:https://blog.csdn.net/liuchuo/article/details/51985824

題解

關於long double的精度及輸入輸出格式
精度
long double精度
精度可以達到20位以上

輸入輸出格式
不管什麼C,C++編譯器,long double —>%Lf,%Le,%Lg, 都是沒錯的
%LE,%LG 似乎也都是沒錯的。
long double —>%Lf,%Le,%Lg

好像%llf也可以,也AC了

double ---->%lf,%le,%lg
float ---->%f,%e,%g
亂用就不好,printf,雖然,不會出大的錯誤,但是表示精度可能不對。
比如
double lf=10000000.3543454353423;

printf ("%f", lf);//表示精度可能就不夠了;

float f =323.43543;

printf ("%lf", f);//表示精度是夠了,不過沒必要,精度太高,浪費了

//float不需要這麼高的精度。

scanf 就跟更不能亂用了。

因為傳遞地址,引數本身沒有問題,資料輸入可能越界,或者不足。
————————————————
這題乙級做過,可以回去再看看~
原文連結:https://blog.csdn.net/qq_41581765/article/details/120010841

#include <bits/stdc++.h>

using namespace std;

int main()
{
#ifdef ONLINE_JUDGE
#else
    freopen("1.txt", "r", stdin);
#endif
    int n;
    cin>>n;
    long double sum=0,value;
    for(int i=1;i<=n;i++){
        cin>>value;
        sum+=value*i*(n-i+1);
    }
    printf("%.2llf",sum);
    return 0;
}

本文來自部落格園,作者:勇往直前的力量,轉載請註明原文連結:https://www.cnblogs.com/moonlight1999/p/15759973.html