23年广大新生赛
- 数组分类:
- 遍历数组,将奇数和偶数分开。
- 分别记录:
- 奇数的最大值 (
f1
)、最小值 (g1
)。 - 偶数的最大值 (
f0
)、最小值 (g0
)。
- 奇数的最大值 (
- 乘积最大化:
- 计算奇数和偶数之间的乘积的最大值,可能的乘积组合有:
- 最大奇数 × 最大偶数。
- 最大奇数 × 最小偶数。
- 最小奇数 × 最大偶数。
- 最小奇数 × 最小偶数。
- 因为我们需要得到最大乘积,所以必须考虑正数与正数相乘和负数与负数相乘的情况。
- 计算奇数和偶数之间的乘积的最大值,可能的乘积组合有:
- 边界检查:
- 如果数组中没有奇数或偶数中的任何一种,直接输出
-1
。
- 如果数组中没有奇数或偶数中的任何一种,直接输出
关键的计算逻辑:
-
奇数和偶数的组合:
- 对于偶数
a[i]
,我们可以计算它与最大奇数 (f1
) 和最小奇数 (g1
) 的乘积。 - 对于奇数
a[i]
,我们可以计算它与最大偶数 (f0
) 和最小偶数 (g0
) 的乘积。
- 对于偶数
-
最大乘积计算:
- 可能的最大乘积是:
最大奇数 × 最大偶数
最大奇数 × 最小偶数
最小奇数 × 最大偶数
最小奇数 × 最小偶数
- 可能的最大乘积是:
-
输出最大乘积:
- 计算出这四种乘积后,返回其中最大的值。
#include <bits/stdc++.h>
using namespace std;int n, a[100005];
int maxEven = INT_MIN, minEven = INT_MAX, hasEven = 0;
int maxOdd = INT_MIN, minOdd = INT_MAX, hasOdd = 0;
int ans = INT_MIN;// 自定义读取函数
int read() {int x = 0, sign = 1; char ch = getchar();while (!isdigit(ch)) { if (ch == '-') sign = -1; ch = getchar(); }while (isdigit(ch)) { x = x * 10 + (ch - '0'); ch = getchar(); }return sign * x;
}int main() {n = read(); // 读取输入的数组长度// 遍历输入的数组,分别更新最大/最小的奇数和偶数for (int i = 1; i <= n; i++) {a[i] = read();if (a[i] % 2 == 0) { // 偶数maxEven = max(maxEven, a[i]);minEven = min(minEven, a[i]);hasEven = 1;} else { // 奇数maxOdd = max(maxOdd, a[i]);minOdd = min(minOdd, a[i]);hasOdd = 1;}}// 如果没有奇数或偶数,输出 -1if (!hasEven || !hasOdd) {puts("-1");return 0;}// 遍历数组,计算最大乘积for (int i = 1; i <= n; i++) {if (a[i] % 2 == 0) { // 如果当前元素是偶数ans = max(ans, a[i] * maxOdd); // 偶数 * 最大奇数ans = max(ans, a[i] * minOdd); // 偶数 * 最小奇数} else { // 如果当前元素是奇数ans = max(ans, a[i] * maxEven); // 奇数 * 最大偶数ans = max(ans, a[i] * minEven); // 奇数 * 最小偶数}}// 输出最终的最大乘积printf("%d\n", ans);return 0;
}
#include <bits/stdc++.h>
using namespace std;int main() {int n;cin >> n; // 输入向量数量vector<int> x(n), y(n), f(n); // 使用 vector 动态数组for (int i = 0; i < n; i++) {cin >> x[i] >> y[i] >> f[i]; // 输入每个向量的 x, y 和 f}double fx = 0, fy = 0;for (int i = 0; i < n; i++) {double d = sqrt(x[i] * x[i] + y[i] * y[i]); // 计算每个向量的模长if (d == 0) continue; // 如果向量为零向量,跳过// 计算单位向量并累加到 fx 和 fyfx += f[i] * x[i] / d;fy += f[i] * y[i] / d;}// 输出合成向量的 x 和 y 分量,保留三位小数cout << fixed << setprecision(3) << fx << " " << fy << endl;return 0;
}
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;int main()
{int n;cin >> n;int a[n]; // 声明数组// 从 0 开始遍历数组for(int i = 0; i < n; i++) {cin >> a[i]; // 读取数组元素}double ans = 0.0;// 从第二个元素开始计算,防止越界for(int i = 1; i < n; i++) {ans += 1.0 / max(a[i], a[i - 1]); // 计算每一对相邻元素的最大值的倒数}// 最后将第一个和最后一个元素的最大值倒数加上ans += 1.0 / max(a[0], a[n - 1]);printf("%.6lf", ans); // 输出答案,保留6位小数return 0;
}
计算期望值:
double ans = 0.0;// 从第二个元素开始计算,防止越界
for (int i = 1; i < n; i++) {ans += 1.0 / max(a[i], a[i - 1]); // 计算每一对相邻元素的最大值的倒数
}
最后,我们需要处理第一个和最后一个元素的最大值的倒数:
a[0]
和a[n-1]
是循环的最后一对相邻题目(第一个和最后一个题目)。- 将它们的最大值倒数加到
ans
中。
关键问题
- 期望的定义:期望值是某事件发生的平均结果,通常是事件发生的概率与结果的乘积。在这道题目中,我们的目标是计算小芳做对的题目的期望数量。
- 相邻题目的选择错误:因为每个题目的答案是从它的选项中随机选择的,因此每道题目做对的概率是与它的选项数相关的。
为什么每道题的期望是相邻选项数的最大值的倒数?
1. 期望值的计算
首先,期望值的计算是基于小芳的错误选择方式:她将第 i
道题的答案抄写到第 i+1
道题上。所以,我们不仅要关注每道题目做对的概率,还要计算相邻题目间如何影响期望。
- 假设第
i
道题目有a[i]
个选项,第i+1
道题目有a[i+1]
个选项。小芳会随机选择第i+1
道题目的答案,并且把它当做第i
道题目的答案。如果她选择的是正确的选项,则第i
道题目得分。
2. 最大值的倒数解释
对于题目中提到的每一对相邻元素的最大值的倒数,它的含义是:
-
每一对相邻的题目,实际上是随机选中其中一题的正确答案来影响另一题的答题选择。换句话说,每一对相邻题目的选项数量决定了其做对的期望值。
-
其中,最大值的倒数代表了每一对相邻题目正确答案的 相对概率。
为什么是 最大值?这是因为:
- 当两道题目选项数分别为
a[i]
和a[i+1]
时,选项数较少的题目被认为更容易做对。因此,做对题目的概率应该考虑相邻题目的选项数的最大值。选择正确答案的概率就等于1 / max(a[i], a[i+1])
。 - 例如,如果第
i
道题有 2 个选项,第i+1
道题有 3 个选项,那么它们的最大选项数是max(2, 3) = 3
,也就是说,第i+1
道题答案的选择会影响第i
道题目做对的概率。
- 当两道题目选项数分别为