AcWing 1239. 乘积最大

AcWing 1239. 乘积最大

1、题目分析

  1. 如果k==n,数字全选
  2. 若k<n
    1. k是偶数,结果一定是非负数,原因如下
      • 负数为奇数个,成对选绝对值最大的负数相乘
      • 负数为偶数个,负负得正
    2. k是奇数
      • 全是负数,结果是负数(从右往左选k个)
      • 否则数组中必定存在一个非负数,选择最大的非负数,还剩k–(偶数)
      • 剩下k–个数,转化为1中k是偶数情况
  3. 规律:
    • 只有当k是奇数时,选取最大的那个数,转化成k–是偶数
    • k是偶数时,左右两成对选取,选择乘积较大的一对,然后更新左右指针
  4. 注意:
    • 当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) //k奇数 
	{
		res=a[r];//选取最大的数,将k转化成偶数
		r--;
		k--;
        //特判一下,如果最大值都是负数,就证明全是负数,那么符号要发生改变
		if(res<0) sign=-1;
	}
	while(k)//双指针
	{
		ll x=(ll)a[l]*a[l+1],y=(ll)a[r]*a[r-1]; //左右两端成对选取,选择乘积打的一对,更新指针,并且k-2
		
		if(x*sign>y*sign){
			res=x%mod*res%mod;// 需要注意的是 :不可以写成(x * res) % mod ,也不可以写成是 res % mod * x % mod    因为x最大是 10^10,如果不先取模的话,和res相乘的结果最大是 10^19,会暴long long。 
			l+=2;
			
		}
		else{
			res=y%mod*res%mod;
			r-=2;
		}
		k-=2;
	}
	printf("%lld",res);
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值