开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 5 天,点击查看活动详情
A. Cherry (贪心思想)
题意: 给定一个长度为n的序列,,找到这个值的最大值 ,其中:
题解:
结论:
这东西 其实等价于这个序列中,相邻的两个数相乘的最大值,即
证明:
以一个长度为3的序列为例:1 3 5
小中大(1 3 5),小大中(1 5 3),中小大(3 1 5),中大小(3 5 1),大中小(5 3 1),大小中(5 1 3)
小中大:
① 如果是 {},为了让结果更优,可以选择 {}
② 如果是 {},同理① 可以选择 {}
③ 如果是 {},最小值在中间这种情况,其实这个序列等价于{},因为 ,
④ 如果是 {},同理③ 等价于{}
⑤ 如果是 {} 和 {},同理①②
证毕。
Code:
const int N = 200010;
int a[N];
signed main()
{
int _;
cin >> _;
while (_--) {
int n;
cin >> n;
for (int i = 1; i <= n; i++) cin >> a[i];
int ans = 0;
for (int i = 1; i <= n - 1; i++) ans = max(ans, a[i] * a[i + 1]);
cout << ans << endl;
}
return 0;
}
B. Cobb(反向暴力枚举)
题意: 给定一个长度为n的序列 和一个整数k
找出这个值的最大值: 其中:
数据范围:
观察到k这个取值范围,最大只能是100。
那么要求这个值 的最大值。
那么便是让: 尽可能大,让 尽可能小。
再观察到 i, j 的取值范围 ,那么当 i,j 足够大的时候, 就没影响了。
所以只需要从后往前枚举,求最大值即可。
Code:
const int N = 200010;
int a[N];
signed main()
{
int _;
cin >> _;
while (_--) {
int n, k;
cin >> n >> k;
for (int i = 1; i <= n; i++) cin >> a[i];
int ans = -inf;
for (int i = n; i >= 1; i--) {
for (int j = i - 1; j >= 1; j--) {
if (i * j <= ans) break;
else ans = max(ans, i * j - k * (a[i] | a[j]));
}
}
cout << ans << endl;
}
return 0;
}
有些人说,循环前150,前200就可以了,这个要通过详细的计算一下,与题目数据也相关,有可能会被hack的(我没试过,在这也不多bb)