题目
大意
给定一个正数序列,一个段定义为连续的子序列。例如,给定序列{0.1,0.2,0.3,0.4},我们有10个细分:(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)。
错误重现
#include<bits/stdc++.h>
using namespace std;
int main() {
int n;
double res=0.0;
cin >> n;
vector<double> vec(n);
for (int i = 0; i < n; i++) {
cin >> vec[i];
}
sort(vec.begin(),vec.end());
vector< vector<double> > dp(n);//n*n
for (int i = 0; i < n; i++) {
dp[i].resize(n);
dp[i][i] = vec[i];
res += dp[i][i];
}
for (int i = 0; i < n; i++) {
for (int j = i+1; j < n; j++) {
//dp[i][j]表示从i到j的字符串的总和
dp[i][j] = dp[i][j - 1] + vec[j];
res += dp[i][j];
}
}
printf("%.2lf", res);
return 0;
}
- 本来打算使用动态规划的思想作题,但是最后内存超出限制
只好更改算法
柳神算法
- 关键点:所以temp引起的总和为temp * i * (n – i + 1) 因此找到数学规律,直接计算即可
#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) * i * (n - i + 1);
}
printf("%.2f", sum / 1000.0);
return 0;
}