我是靠谱客的博主 搞怪大炮,最近开发中收集的这篇文章主要介绍1049. 数列的片段和,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

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;
}

这是最后一次提交的代码,顺利通过,感觉还是蛮幸运,虽然出了不少错误,但还是很快发现了。
感觉以后在做算法题的时候,要经全力去思考,找最优化的代码,而不是一出现问题就去百度看别人的博客寻求解决办法。
还有就是出现问题了一定不要急,回去认真读题,认真扣字眼,看是不是自己哪里理解错了,是问题就一定有解法,只是代价问题。



最后

以上就是搞怪大炮为你收集整理的1049. 数列的片段和的全部内容,希望文章能够帮你解决1049. 数列的片段和所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(76)

评论列表共有 0 条评论

立即
投稿
返回
顶部