ACM集训队每周程序设计竞.赛(2)-E-经典的贪心问题

有一天,一个名为小明的程序员遇到了一个棘手的问题:
如何从一堆数中选出恰好 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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值