AcWing 1239. 乘积最大
1、题目分析
- 如果k==n,数字全选
- 若k<n
- k是偶数,结果一定是非负数,原因如下
- 负数为奇数个,成对选绝对值最大的负数相乘
- 负数为偶数个,负负得正
- k是奇数
- 全是负数,结果是负数(从右往左选k个)
- 否则数组中必定存在一个非负数,选择最大的非负数,还剩k–(偶数)
- 剩下k–个数,转化为1中k是偶数情况
- 规律:
- 只有当k是奇数时,选取最大的那个数,转化成k–是偶数
- k是偶数时,左右两成对选取,选择乘积较大的一对,然后更新左右指针
- 注意:
- 当k是负数,并且所有数都是负数的时候,先取最大的数,剩下的全是负数,此时应该选择乘积较小的对数,那么符号就要改变
- sign标记正负
2、算法:贪心+双指针
3、代码实现
#include<iostream>
#include<cstdio>
#include<algorithm>
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++) scanf("%d",&a[i]);
sort(a,a+n);
ll res=1;
int l=0,r=n-1;
int sign=1;
if(k%2)
{
res=a[r];
r--;
k--;
if(res<0) sign=-1;
}
while(k)
{
ll x=(ll)a[l]*a[l+1],y=(ll)a[r]*a[r-1];
if(x*sign>y*sign){
res=x%mod*res%mod;
l+=2;
}
else{
res=y%mod*res%mod;
r-=2;
}
k-=2;
}
printf("%lld",res);
return 0;
}