日常训练 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 个元素开始的前缀,但是对于前后都负的前缀积计算时前缀积最小值是不能简单设初值处理,只能记录前缀积最小值存不存在,而很难设初值处理。
给定一个由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; }
相关文章推荐
- 日常训练 20170612 星之船
- QUST日常训练(1)北极熊和大象
- 日常训练20161012 方块游戏
- 日常训练20161014 成绩调研
- [日常训练] 距离之和
- [日常训练] 保存名画
- [日常训练] 单词
- QUST日常训练(1)分数修改
- 日常基本功训练方法及要求与标准。
- 日常训练 20170602 Book
- 日常训练20161013 括号表达式
- 日常训练20161031 量化交易 trade
- 日常训练小结
- QUST日常训练(1)乘积最大
- 日常训练 20170531 数字
- 日常训练 20170602 Equation
- 日常训练20161012 道路网
- 日常训练20161013 棋盘上的象
- 日常训练20161014 跟踪
- [日常训练] 太空飞船