AtCoder Contest 173 E - Multiplication 4

题目链接

**

大体思路

**

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;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值