1049 数列的片段和 (20 分)(C++)

24 篇文章 1 订阅
2 篇文章 0 订阅

在这里插入图片描述

Notice:
1.一开始直接写嵌套循环,发现超时。所以需要用数学方法去求解。
	后参考别人博客,发现其规律:
	
	先观察一个数,例如,对于N=4的数列中序列号为3的数所在的片段如下:
	   (起点为1)[(1,2,3),(1,2,3,4)];
	   (起点为2)[(2,3),(2,3,4)];
	   (起点为3)[(3),(3,4)];
	可以看出来,包含第i个数的片段中,片段的起始可以是1,2,3..i,一共i种选择,
	(如包含3的片段有123三种选择) 片段的结尾可以是i,i+1,...n,一共n-i+1种选择。
	(如包含3的片段有34两种选择)。
	由此推广,对于长度为N的数列中序列号为i的数,所在的片段可分为i个部分,第i部分起点为i,
	终点分别为i,i+1,i+2,...,N,共(N-i+1)个,故序列i的出现次数为i*(N-i+1)。
	http://www.bubuko.com/infodetail-3010293.html
2.关于long long sum:

“N比较大时,double类型的值多次累加导致的精度误差,因为输入为十进制小数,存储到double中时,
计算机内部使用二进制表示,且计算机的字长有限,有的十进制浮点数使用二进制无法精确表示
只能无限接近,在字长的限制下不可避免会产生舍入误差,这些细微的误差在N较大时多次累加
会产生较大误差,所以建议不要使用double类型进行多次累加的精确计算,而是转为能够精确存储
的整型。尝试把输入的double类型的值扩大1000倍后转为long long整型累加,同时使用
long long类型保存sum的值,输出时除以1000.0转为浮点型再输出(相当于把小数点向后移动3位后
再计算,避免double类型的小数部分存储不精确,多次累加后对结果产生影响) 但我觉得乘以1000
也未必严谨,可能测试样例最小只有小数点后三位,如果测试样例变成小数点后四位、五位、六位,
乘以1000相当于直接在小数点后三位处截断,而原本第四五六位经过多次累加进位后依然可能会引起
精度问题,但如果乘以10000就会超出long long的值,我认为最精确的应该是截取到所有小数中最大
的位数的那一位。。可能我的想法有疏漏,经过测试,测试样例确实没有超过小数点后三位,
虽然修改为乘以1000后代码已经AC,但如果对测试样例稍加修改,可能又会导致不AC了…
所以这道题先打个问号吧,我猜可能将来题目样例还会被修改…”

我的 (该代码超时)

#include <iostream>
#include <cstdio>
using namespace std;
int main(){
    int n;
    cin >> n;
    float a[n];
    for(int i = 0;i < n;i++){
        cin >> a[i];
    }
    float sum1 = 0,sum2 = 0;
    for(int i = 0;i < n;i++){
            sum1 = 0;
        for(int j = i;j < n;j++){
            sum1 += a[j];
            sum2 += sum1;
        }
    }
    printf("%.2f",sum2);
    return 0;
}

柳诺的代码

#include <iostream>
using namespace std;
int main() {
    int n;
    cin >> n;
    double temp;
    long long sum = 0;
    for(int i = 1;i <= n;i++){
        cin >> temp;
        sum += (long long)(temp * 1000) * i * (n - i + 1); 
    }
    printf("%.2f",sum / 1000.0);
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值