乘积最大(贪心)

给定N个整数,需要从中选出K个数使乘积最大,输出乘积对1000000009取模的结果。当K等于N时,直接相乘;K大于N且N为偶数时,以两个一组比较并选取最大乘积;K大于N且N为奇数时,若无正数则选取最大负数,否则同样以两两比较选取最大乘积。
摘要由CSDN通过智能技术生成

给定 N 个整数 A1,A2,…AN。

请你从中选出 K 个数,使其乘积最大。

请你求出最大的乘积,由于乘积可能超出整型范围,你只需输出乘积除以 1000000009 的余数。

注意,如果 X<0, 我们定义 X 除以 1000000009 的余数是负(−X除以 1000000009 的余数,即:0−((0−x)%1000000009)

输入格式

第一行包含两个整数 N 和 K。

以下 N 行每行一个整数 Ai

输出格式

输出一个整数,表示答案。

数据范围

1≤K≤N≤105
−105≤Ai≤105

输入样例1:

5 3
-100000
-10000
2
100000
10000

输出样例1:

999100009

输入样例2:

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

输出样例2:

-999999829
难度:中等
时/空限制:1s / 64MB
总通过数:3884
总尝试数:12657
来源:第九届蓝桥杯省赛C++B组
算法标签

挑战模式

 

分情况讨论:

第一种,n==k直接全部乘;

第二种 n>k &&n%2==0 排序,以两个一组排序比较,大的就乘

第三种 n>k&&n%2==1 排序,如果没有正数,从大到小乘,如果有正数就变为第二种情况,只不过 n=n-1 k=k-1 

#include <iostream>
#include <algorithm>
using namespace std;
constexpr int N=1e5+7,mod=1e9+9;
typedef long long ll;
int n,k;
ll a[N];
ll res=1;
int main(){
    scanf("%d%d",&n,&k);
    for(int i=1;i<=n;i++){
        scanf("%lld",&a[i]);
    }
    sort(a+1,a+n+1);
    if(n==k){
        for(int i=1;i<=n;i++){
            res=res%mod*(ll)a[i]%mod;
        }
    }
    else if(k%2==0){
        int t1=1,t2=n;
        k/=2;
        while(k--){
            ll x=(ll)a[t1]*(ll)a[t1+1];
            ll y=(ll)a[t2]*(ll)a[t2-1];
            if(x>y) {
                res = res%mod * a[t1]%mod * a[t1 + 1] % mod;
                t1+=2;
            }
            else{
                res = res%mod * a[t2]%mod * a[t2 - 1] % mod;
                t2-=2;
            }
        }
    }
    else if(k%2==1) {
        if (a[n] < 0) {
            for (int i = n; i > n - k; i--) {
                res = res % mod * a[i] % mod;
            }
        } else {
            res = a[n];
            int t1 = 1, t2 = n-1;
            k /= 2;
            while (k--) {
                ll x = (ll) a[t1] * (ll) a[t1 + 1];
                ll y = (ll) a[t2] * (ll) a[t2 - 1];
                if (x > y) {
                    res = res % mod * a[t1] % mod * a[t1 + 1] % mod;
                    t1 += 2;
                } else {
                    res = res % mod * a[t2] % mod * a[t2 - 1] % mod;
                    t2 -= 2;
                }
            }
        }
    }
    printf("%lld\n",res);
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

q619718

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值