PAT|1104 Sum of Number Segments(数学)

题目

在这里插入图片描述

大意

给定一个正数序列,一个段定义为连续的子序列。例如,给定序列{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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值