有一天,一个名为小明的程序员遇到了一个棘手的问题:
如何从一堆数中选出恰好 k个数,使得它们的乘积最大。
小明像往常一样花了很长时间思考,却没有得到一个可行的解决方案。这时,他的朋友阿福来找他帮忙,看到小明一脸沮丧,阿福开玩笑说:“嘿,看起来你需要一个数学奇才才能解决这个问题!” 小明想了想,然后说:“没错,我要找到这个数学奇才!”,于是两个人一起开始寻找这个数学奇才。他们沿着街道走了很长时间,终于在一个古老的图书馆里找到了这个传说中的数学奇才。这个数学奇才非常友善,听到小明的问题后,他立刻开始解释: “这是一个经典的问题,你需要使用贪心算法来解决它。” 阿福想了想,回答道:“哦,就是我们需要贪心地选择那些最大的数,对吧?” 数学奇才笑而不语。那么,请问你是否悟到了数学奇才的话中的真谛?
请你尝试解决这个问题,并将答案对
取模。
输入
输入共两行,
第一行包含两个正整数
第二行包含
个正整数
输出
输出共一行,
包含一个自然数表示从
个数中选择
个数的最大乘积对于
的取模
样例输入 复制
4 2
1 2 -3 -4
样例输出 复制
12
正负的处决
#include <bits/stdc++.h>
using namespace std;
const int MOD = 1e9+7;
void solve()
{
int n,k,l,r,flag=1;
long long ans=1,x,y;
scanf("%d%d",&n,&k);
vector<int>ve(n);
for(int i=0;i<n;i++)
scanf("%d",&ve[i]);
sort(ve.begin(),ve.end());
l=0,r=n-1;
if(k&1)//k为奇数
{
ans=ve[r--];k--;//ans=最大的数,k变成偶数
if(ans<0)flag=-1;//最大的数为负数,flag=-1
}//特判k为奇数,所有数均为负数的情况
while(k)//flag=1时,左负右正||全为正
{
x=1ll*ve[l]*ve[l+1];//取左边两个数相乘
y=1ll*ve[r]*ve[r-1];//取右边两个数相乘
if(x*flag>y*flag)//必为正数(flag=1时)
{ans*=x%MOD;ans%=MOD;l+=2;}
else
{ans*=y%MOD;ans%=MOD;r-=2;}
k-=2;
}
printf("%lld\n",(ans+MOD)%MOD);
}
signed main() {
solve();
return 0;
}