一看见有下面这个就不简单
Java直接原地超时,上StreamTokenizer
也不行,就不贴上来了,然后。。。
全网的题解没有一个能AC的🤪🤪🤪
最后还是看了柳神的更新,找到了数据更新点
解题思路:
将数列中的每个数字读取到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的值
数据更新
N比较大时,double
类型的值多次累加导致的精度误差,因为输入为十进制小数,存储到double中时,计算机内部使用二进制表示,且计算机的字长有限,有的十进制浮点数使用二进制无法精确表示只能无限接近,在字长的限制下不可避免会产生舍入误差,这些细微的误差在N较大时多次累加会产生较大误差,所以建议不要使用double
类型进行多次累加的精确计算,而是转为能够精确存储的整型。尝试把输入的double
类型的值扩大1000倍后转为long long
整型累加,同时使用long long
类型保存sum的值,输出时除以1000.0
转为浮点型再输出(相当于把小数点向后移动3位后再计算,避免double
类型的小数部分存储不精确,多次累加后对结果产生影响)
但是也有问题,因为测试用例的不同小数点的位数不一样,我在一天的两个时段分别测试了5遍:中午第三个测试点依旧过不了,晚上六点半左右就一直都能过,所以代码还有不成熟的地方,每次4个测试用例都需要知道是几分位的小数,所以这是个撞大运的代码,如果为了AC多提交几次就够了
//柳
#include <iostream>
using namespace std;
int main() {
int n;
cin >> n;
long long sum = 0;
double temp;
for (int i = 1; i <= n; i++) {
cin >> temp;
sum += (long long)(temp * 1000) * (n - i) * (i + 1);
}
printf("%.2f", sum / 1000.0);
return 0;
}