**
大体思路
**
N个数取K个数的积最大,分为四种情况
第一种:全是正数,则取最大的K个数的积
第二种:没有正数,则取最大的K个数的积
第三种:有正有负,按照绝对值排列,对最大的K个的值进行判断,如果值为正,则直接输出,如果为负则判断前N-K个数中最大的正数于后K个数中的最小负数交换,将前N-K个数中最大的负数于后K个数中最小的正数交换,比较大小即可
某篇博客的解法:
#include <iostream>
#include <stdio.h>
#include <vector>
#include <algorithm>
using namespace std;
long long n, k;
long long ans = 1;
long long l_neg = -1,l_pos = -1, r_neg = -1, r_pos = -1;
//l_neg表示前N-K项最大的负数,l_pos表示前N-K项最大的正数,r_neg表示后K项最小负数,r-pos表示后K项最小正数
const long long int M = 1000000007;
bool cmp(long long int a,long long int b)//按照绝对值排序
{
return abs(a) < abs(b);
}
long long int calc(vector<long long int> a)
{
long long temp = 1;
for(long long int i = n - k; i < n; i++)
temp = (temp * a[i]) % M;
return (temp+M)%M;
}
int main()
{
cin >> n >> k;
vector<long long int> a(n, 0);
for(long long int i = 0; i < n; i++)
{
cin >> a[i];
}
sort(a.begin(), a.end(), cmp);
for(long long int i = n - k; i < n; i++)
{
ans = (ans * a[i]) % M;//计算后K项的积
if(r_pos == -1 && a[i] > 0)//找出后K项中最小的正数
r_pos = i;
if(r_neg == -1 && a[i] < 0)//找出后K项中最小的负数
r_neg = i;
}
for(long long int i = n - k - 1; i >= 0; i--)
{
if(l_pos == -1 && a[i] > 0)//找出前N-K项中最大的正数
l_pos = i;
if(l_neg == -1 && a[i] < 0)//找出前N-K项中最大的负数
l_neg = i;
}
if(ans < 0 && n != k)
{
if(r_pos == -1)//如果后K项没有正数
{
if(l_pos == -1)//如果前N-K项也没有正数
{
ans = 1;
for(long long int i = 0; i < k; i++)
ans = (ans * a[i]) % M;
}
else
{
swap(a[l_pos], a[r_neg]);
ans = calc(a);
}
}
else
{
if(l_neg == -1)
{
swap(a[l_pos], a[r_neg]);
ans = calc(a);
}
else if(l_pos == -1)
{
swap(a[l_neg], a[r_pos]);
ans = calc(a);
}
else
{
vector<long long int> c1 = a;
vector<long long int> c2 = a;
swap(c1[l_neg], c1[r_pos]);
swap(c2[l_pos], c2[r_neg]);
ans=(abs(a[l_neg]*a[r_neg])>abs(a[l_pos]*a[r_pos]))?calc(c1):calc(c2);//判断交换之后哪一个比较大
}
}
}
cout << (ans+M)%M << endl;
return 0;
}
在上面基础上自己修改的解法
#include <bits/stdc++.h>
#define ll long long
using namespace std;
ll a[200001];
ll mod=1e9+7;
ll js(int k,int i,int flag){
ll ans=1;
while(k){
ans=(ans*(a[i]%mod))%mod;
if(flag) i--;
else i++;
k--;
}
return (ans+mod)%mod;
}
bool cmp(int q,int w){
return abs(q)<abs(w);
}
int main()
{
ios::sync_with_stdio(false);cin.tie(0);
int n,k1;
cin>>n>>k1;
for (int i=0;i<n;i++){
cin>>a[i];
}
int k=k1;
sort(a,a+n,cmp);
int i=n-1;
ll ans=1;
int fneg=-1;int fpos=-1;
while(k1){
ans=(ans*a[i])%mod;
if(a[i]<0)
{
fneg=i;
}
if(a[i]>0){
fpos=i;
}
i--,k1--;
}
// 如果ans为正数 就是最大的数
// 为负数 就要把已经选择的k个数里面的最大负数与n-k个数中的最大正数交换
//或者k个数里面的最小正数与n-k个数里面的最大负数交换
int kneg=-1;int kpos=-1;
for (int j=0;j<n-k;j++){
if(a[j]<0){
kneg=j;
}
if(a[j]>0){
kpos=j;
}
}
//分n-k有没有正数和负数 在根据k 分情况
if(ans<0&&n!=k){
if(kpos==-1){
if(fpos==-1){
ans=js(k,0,0);
}
else{
swap(a[kneg],a[fpos]);
ans=js(k,n-1,1);
}
}
else{
if(fpos==-1){
swap(a[kpos],a[fneg]);
ans=js(k,n-1,1);
}
else{
if(kneg==-1){
swap(a[kpos],a[fneg]);
ans=js(k,n-1,1);
}
else{
swap(a[kpos],a[fneg]);
ans=js(k,n-1,1);
swap(a[kpos],a[fneg]);
swap(a[kneg],a[fpos]);
ll ans2=js(k,n-1,1);
swap(a[kneg],a[fpos]);
ans=(abs(a[kpos]*a[fpos])>abs(a[kneg]*a[fneg]))?ans:ans2;
}
}
}
}
cout<<(ans+mod)%mod<<endl;
return 0;
}