您的位置:首页 > 其它

日常训练 20170612 钥匙

2017-06-12 21:29 183 查看
题意简述:

  给定一个由N个实数组成的序列 a1,a2,…,an,你需要求出对于所有的满足 1≤i≤j≤n 整数 i,j,∏ri=lai 的最大值是多少。

输入格式:

  第一行是一个整数 n。

  第二行有 n 个由空格分隔的实数 a1,a2,a3,…,an−1,an。

输出格式:

  如果答案 k=0 或者 1≤|k|<10,那么请直接输出答案并保留三位小数。否则,若答案用科学计数法表示为 a×10b(其中 1≤|a|≤10,b 是整数),你需要输出 aEb,其中 a 要保留三位小数。

题解:

  一开始想只要取个对数就能随便做了,但写着写着就感觉细节很麻烦,乘积有正有负,所以要正负分开考虑,如果答案也分正负更新会写得很麻烦,不难发现元素不少于 2 个时答案非负(可以用前缀积和鸽巢原理简单证明)。那么我们做了前缀积之后只要用前后两个前缀积同正或同负来更新了。还有一些初值细节,比如对于前后同正的前缀积计算时前缀积最小值可以设初值为 1 ,表示可以是原序列从第 1 个元素开始的前缀,但是对于前后都负的前缀积计算时前缀积最小值是不能简单设初值处理,只能记录前缀积最小值存不存在,而很难设初值处理。

#include<bits/stdc++.h>
typedef long double ld;
const int N = 1e5 + 10;
const long double eps = 1e-7;
int n, mxf, sumf;
long double mx, mn, sum, temp, a
;
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; i++)
scanf("%Lf", &a[i]);
if (n == 1) {
if (fabs(a[1]) < 10 && fabs(a[1]) >= 1) {printf("%.3Lf\n", a[1]); return 0; }
if (a[1] < -eps) printf("-"), a[1] = -a[1];
a[1] = log(a[1]) / log(10);
printf("%.3fE%d\n", pow(10, a[1] - floor(a[1])), (int)floor(a[1]));
return 0;
}

mx = -100;

sumf = 1;
sum = 0;
mn = 0;
bool updated = 0;
for (int i = 1; i <= n; i++) {
if (fabs(a[i]) < eps) {sumf = 1; sum = 0; mn = 0; updated = 0; continue;}
sum += log(fabs(a[i])) / log(10);
if (a[i] < -eps) sumf *= -1;
if (sumf == -1) {
if (updated)
mx = std::max(mx, sum - mn),
mn = std::min(mn, sum);
else
mn = sum,
updated = 1;
}
}

sumf = 1;
sum = 0;
mn = 0;
for (int i = 1; i <= n; i++) {
if (fabs(a[i]) < eps) {sumf = 1; sum = 0; mn = 0;continue;}
sum += log(fabs(a[i])) / log(10);
if (a[i] < -eps) sumf *= -1;
if (sumf == 1)
mx = std::max(mx, sum - mn),
mn = std::min(mn, sum);
}

if (mx < 1)
printf("%.3f\n", pow(10, mx));
else
printf("%.3fE%d\n", pow(10, mx - floor(mx)), (int)floor(mx));
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  细节