您的位置:首页 > 其它

1049. 数列的片段和

2017-03-13 12:44 99 查看
1049. 数列的片段和

给定一个正数数列,我们可以从中截取任意的连续的几个数,称为片段。例如,给定数列{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。

输入格式:

输入第一行给出一个不超过105的正整数N,表示数列中数的个数,第二行给出N个不超过1.0的正数,是数列中的数,
其间以空格分隔。
输出格式:

在一行中输出该序列所有片段包含的数之和,精确到小数点后2位。

输入样例:

4

0.1 0.2 0.3 0.4 

输出样例:

5.00

刚接手题目的时候觉得应该是用dp,dp[i]存放的是从1-i数字相加的和,这样可以用一个双层循环,直接暴力应该
是三层循环,肯定不通过。第一层循环是起点位置,第二层循环是step即每次加和的长度。

#include <stdio.h>
#define MAX 100005

double a[MAX];
double dp[MAX];

int main()
{

int n;
scanf( "%d", &n );
for ( int i = 1 ; i <= n ; ++ i ) {
scanf( "%lf", &a[i] );
dp[i] = a[i] + dp[i-1];
}
double sum = 0;
//  跨度  例: step=0时 计算 a[i]和 step=1时 计算a[i]+--+a[i+1];
for ( int step = 1 ; step <= n ; ++ step ) {
for ( int j = step ; j <= n ; j ++ ) {
sum += dp[j]-dp[j-step];
}
}
printf( "%.2lf", sum );

return 0;
}


结果显示2,3两个测试点超时了,才发现dp不行,两层都会超时,看来还有更优化的一层循环的方法。

想了想可以列举出每个数字在求和的时候出现的次数,由3个数字到4个数字到n个数字的推广,得出n个数中第i个数出现的次数为( i*(n-i+1) )(大家可以自己动手推一下)

就赶紧改了改代码交了。

#include <stdio.h>
#define MAX 100005

double a[MAX];

int main()
{
//  第i个数  需要计算 i*(n-i+1) i=1-n
int n;
double sum = 0;
scanf( "%d", &n );
for ( int i = 1 ; i <= n ; ++ i ) {
scanf( "%lf", &a[i] );
sum += i*( n-i+1 )*a[i];
}
printf( "%.2lf", sum );
return 0;
}


明显可以看到已经优化为O(n)的算法了,就又兴致勃勃的去提交。结果显示3,4答案错误, 一下懵了,报的错误是答案错误而不是超时,说明算法是优化了可能出现了什么

逻辑错误,第一感觉是出现了特殊数据,就赶紧回去读题。完了又感觉没漏掉什么,又想是不是算法出错了,看了看规律确实没错,又想到是不是数据溢出了,但感觉不会啊,

我可是用的double存储的数据,怎么会溢出呢。苦思冥想之际,突然发现 规律中  i*(n-i+1)*a[i], 虽然最后结果是double,但是前面两个整数相乘的时候发生了局部溢出,

就赶紧有换了下表达式的顺序,  sum += a[i]*i*(n-i+1), 这样在前两个相乘的时候就已经转换为double,应该不会出问题了。

#include <stdio.h>
#define MAX 100005

double a[MAX];

int main()
{
//  第i个数  需要计算 i*(n-i+1) i=1-n
int n;
double sum = 0;
scanf( "%d", &n );
for ( int i = 1 ; i <= n ; ++ i ) {
scanf( "%lf", &a[i] );
//  i*(n-i+1)会溢出 所以先乘double
sum += a[i]*i*( n-i+1 );
}
printf( "%.2lf", sum );
return 0;
}


这是最后一次提交的代码,顺利通过,感觉还是蛮幸运,虽然出了不少错误,但还是很快发现了。

感觉以后在做算法题的时候,要经全力去思考,找最优化的代码,而不是一出现问题就去百度看别人的博客寻求解决办法。

还有就是出现问题了一定不要急,回去认真读题,认真扣字眼,看是不是自己哪里理解错了,是问题就一定有解法,只是代价问题。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: