0
点赞
收藏
分享

微信扫一扫

乘积最大(贪心)

陌岛 2022-02-05 阅读 82

输入样例1:

5 3
-100000
-10000
2
100000
10000

输出样例1:

999100009

输入样例2:

5 3
-100000
-100000
-2
-100000
-100000

输出样例2:

-999999829

分析:这是一个贪心题,需要分情况进行讨论,我们需要单独存储正数和负数(0按正数处理),第一种情况,给定的数的个数与要选的数的个数相同,那么这个直接全选就行了,还有一种情况就是全是负数,这个也要单独分情况进行讨论,我们先对负数进行排序,如果要是要选的数的个数为奇数,那么最终结果一定是负数,那么我们就从最大的负数开始选,选k个数为止,因为负数越大则其绝对值越小,如果要是要选的数的个数为偶数,因为最后结果是一个正值,那么我们就从最小的负数开始选,选完为止。

下面我们着重看一下存在正数的时候应该怎么选,首先如果不是把所有的数全选(即至少可以空出一个数不选)且存在正数,那么最后结果一定可以是个非负数(充其量我们不选一个正数或者不选一个负数,这个根据我们的乘积正负性来决定),这个时候如果所选的数的个数k是一个奇数,那我们最终选的数中至少存在一个正数,那么为了使乘积最大,我们就先选上正数中最大的那个数,如果k是偶数则不用做这步处理,剩下我们就只需要选择偶数个数了,我们依次比较绝对值最大的两个负数的乘积和两个正数的乘积,(需要注意的是我们一定要成对成对地选),谁大选谁,直到选完为止,这样就是最优解了,具体代码写的比较复杂,下面是代码:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<vector>
#include<algorithm>
#include<map>
#include<cmath>
#include<queue>
using namespace std;
const int N=1e5+10,mod=1000000009;
typedef long long ll;
ll z[N],f[N];
int main()
{
	int n,k;
	int zcnt=0,fcnt=0;
	cin>>n>>k;
	ll t;
	for(int i=1;i<=n;i++)
	{
		scanf("%lld",&t);
		if(t>=0) z[++zcnt]=t;//包含0 
		else f[++fcnt]=t; 
	}
	sort(z+1,z+zcnt+1);
	sort(f+1,f+fcnt+1);
	ll ans=1;
	if(fcnt+zcnt==k)
	{
		for(int i=1;i<=fcnt;i++)
			ans=ans*z[i]%mod;
		for(int i=1;i<=zcnt;i++)
			ans=ans*z[i]%mod;
		if(fcnt&1&&ans) printf("-");
		printf("%lld",(ans+mod)%mod);
		return 0;
	}
	if(zcnt==0)//只存在负数
	{
		if(k&1)//所选数的个数为奇数,那么就从负数中较大的开始选 
		{
			printf("-");
			for(int i=fcnt;i>fcnt-k;i--)
				ans=ans*(-f[i])%mod;
		}
		else//所选数的个数为偶数,那么就从负数中较小的开始选
		{
			for(int i=1;i<=k;i++)
				ans=ans*f[i]%mod;
		}
	}
	else//存在正数 
	{
		if(k&1)//所选数的个数为奇数,则先把正数中值最大的数选出来,再进行比较选取其他数 
			ans=ans*z[zcnt--]%mod,k--;
		int i,j;
		for(i=1,j=zcnt;i<=fcnt&&j>0&&k;)
		{
			if(f[i]*f[i+1]>z[j]*z[j-1])//选两个当前可选的最小负数 
			{
				ans=f[i]*f[i+1]%mod*ans%mod;
				i+=2;
				k-=2;
			}
			else//选两个当前可选的最大正数 
			{
				ans=z[j]*z[j-1]%mod*ans%mod;
				j-=2;
				k-=2;
			}
		}
		while(i<=fcnt&&k)
		{
			ans=f[i]*f[i+1]%mod*ans%mod;
			i+=2;
			k-=2;
		}
		while(j>0&&k)
		{
			ans=z[j]*z[j-1]%mod*ans%mod;
			j-=2;
			k-=2;
		}
	}
	printf("%lld",(ans+mod)%mod);
	return 0;
}
举报

相关推荐

0 条评论