根据题意,若要取k个数字,使乘积最大,则为了简化求解,首先要进行排序,其次针对k的取值进行分情况。
1. k = n, 则最大乘积,只有数据全部取这一种情况;
2. k < n且k为偶数,则可以成对进行取数,且一定可以使乘积最后取到最大的正数。
3. k < n且k为奇数,则可以先取排序后最大的数据,而后选取个数便成为了偶数个,即又可成对取。而针对这种情况,若数据全为负数,最后乘积一定为负数,则此时需要做一个标记,与乘积为正数进行区分;若其中存在正数,则最后结果也一定会为正。
由上分析,问题便都转化为成对取偶数个数据。既为成对取,便可考虑双指针算法。两个指针一个在前,一个在后,可比较最小的两个数的乘积与最大的两个数的乘积,取较大的那个。两个指针也相应的前进两步,以此类推,即可得。
`
#include <iostream>
#include <algorithm>
#include <cstring>
// #include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 100010, mod = 1000000009;
int a[N];
int n, k;
int main()
{
cin >> n >> k;
for(int i = 0;i < n;i ++)
cin >> a[i];
sort(a, a + n);//一定要先排序
int res = 1;
int l = 0, r = n - 1;
int sign = 1;
if(k & 1) {//判断k是否为奇数(奇数的二进制末位一定为1,与1进行与运算,结果为1。且与运算更加快速)
res = a[r --];
if(res < 0)
sign = -1;//最大值为负,做标记,表明乘积为负数
k --;
}
while(k) {
LL x = (LL)a[l] * a[l + 1], y = (LL)a[r - 1] * a[r];
if(x * sign > y * sign) {//比较
res = x % mod * res % mod;//注意,此处不等于(x % mod) * (res % mod),此处意为先对x进行取余,与res相乘之后,对乘积再取余
l += 2;
}else {
res = y % mod * res % mod;
r -= 2;
}
k -= 2;
}
cout << res << endl;
return 0;
}`