第九届蓝桥杯【C/C++省赛B组】【第十题:乘积最大】

11人阅读 评论(0) 收藏 举报
分类:

题目:

给定N个整数A1, A2, … AN。请你从中选出K个数,使其乘积最大。

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

注意,如果X<0, 我们定义X除以1000000009的余数是负(-X)除以1000000009的余数。

即:0-((0-x) % 1000000009)

【输入格式】
第一行包含两个整数NK。  
以下N行每行一个整数Ai。  

对于40%的数据,1 <= K <= N <= 100  
对于60%的数据,1 <= K <= 1000  
对于100%的数据,1 <= K <= N <= 100000  -100000 <= Ai <= 100000  

【输出格式】
一个整数,表示答案。
【输入样例】
5 3 
-100000   
-10000   
2   
100000  
10000  

【输出样例】
999100009
再例如:
【输入样例】
5 3 
-100000   
-100000   
-2   
-100000  
-100000

【输出样例】
-999999829

解题思路:

先按照绝对值从大到小排序

①假如选的k个数中必定有0,则结果为0

②假如都是负数,此时若k为偶数,则选前k个数即可,若k为奇数,则只能从小的开始选k个数

③假如都为正数,选前k个数即可

④假如正负都有,此时,若前k个数有偶数个负数,则选前k个数即可

若前k个数有奇数个负数,则我们看看能不能从后面选一个大正数跟前面的小负数做交换,或者从后面选一个大负数跟前面的小正数做交换,二者取结果大的.

此时分完所有情况若结果还为负数,我们看看输入是否有0,有零结果即为0,否则就只能输出这个负数了.

代码:

#include<bits/stdc++.h>
#define mem(a,b) memset(a,b,sizeof(a))
#define mod 1000000009
using namespace std;
typedef long long ll;
const int maxn = 1e6+5;
const double esp = 1e-7;
const int ff = 0x3f3f3f3f;
map<int,int>::iterator it;

struct node
{
    ll x;
    int f;
}a[maxn];

int n,k;

bool cmp(node x,node y)
{
    return x.x> y.x;
}

ll solve(int o)
{
    ll ans = 1;
    int cnt = 0;
    if(o == 0)//从前往后乘 
    {
        for(int i = 1;i<= k;i++)
        {
            ans = (ans*a[i].x)%mod;
            if(a[i].f == 1)
                cnt++;
        }
    }
    else//从后往前乘 
    {
        for(int i = n;i> n-k;i--)
        {
            ans = (ans*a[i].x)%mod;
            if(a[i].f == 1)
                cnt++;
        }
    }

    if(cnt&1)
        return ans*(-1);
    return ans;
}

int main()
{
    cin>>n>>k;

    int flag = 0;
    int cnt = 0;
    for(int i = 1;i<= n;i++)
    {
        scanf("%lld",&a[i].x);
        if(a[i].x< 0)
        {
            a[i].f = 1;
            a[i].x = -a[i].x;
            cnt++;
        }
        else if(a[i].x> 0)
            a[i].f = 0;
        else
        {
            i--;n--;//我们不记录0,0只做迫不得已的选择 
            flag = 1;
        }
    }

    sort(a+1,a+n+1,cmp);

    ll ans = 0;

    if(n< k)//如果必须选0 
        ans = 0;
    else if(cnt == n)//如果都为负数 
    {
        if(k&1)
            ans = solve(1);
        else
            ans = solve(0);
    }
    else if(cnt == 0)//如果都为正数 
        ans = solve(0);
    else
    {
        int tmp = 0;
        for(int i = 1;i<= k;i++)
            if(a[i].f == 1)
                tmp++;

        if(tmp%2 == 0)//如果前k大的数有偶数个负数 
            ans = solve(0);
        else
        {
            ans = -1;//将其设置为负数 
            //尝试将前k个里面一个绝对值最小负数和后面最大正数交换 
            int p = -1,q = -1;
            for(int i = k+1;i<= n;i++)
                if(a[i].f == 0)
                {
                    q = i;
                    break;
                }
            for(int i = k;i>= 1;i--)
                if(a[i].f == 1)
                {
                    p = i;
                    break;
                }

            if(p!= -1&&q!= -1)
            {
                swap(a[p],a[q]);
                ans = solve(0);
                swap(a[p],a[q]);
            }

            //尝试将前k个里面一个最小正数和后面绝对值最大正数交换
            p = -1,q = -1;
            for(int i = k+1;i<= n;i++)
                if(a[i].f == 1)
                {
                    q = i;
                    break;
                }
            for(int i = k;i>= 1;i--)
                if(a[i].f == 0)
                {
                    p = i;
                    break;
                }

            if(p!= -1&&q!= -1)
            {
                swap(a[p],a[q]);
                ans = max(ans,solve(0));
                swap(a[p],a[q]);
            }

            //假如结果仍然小于0,我们只能尝试从最后往前乘了 
            if(ans< 0)
                ans = solve(1); 
        }
    }

    if(ans< 0)
        if(flag)//这时候0派上用场了 
        {
            cout<<0<<endl;
            return 0;
        }
    cout<<ans<<endl;

    return 0;
}
查看评论

2018省赛第九届蓝桥杯真题C语言B组第十题题解 乘积最大

2018第九届蓝桥杯C++省赛B组[最新题解汇总]标题:乘积最大给定N个整数A1, A2, ... AN。请你从中选出K个数,使其乘积最大。  请你求出最大的乘积,由于乘积可能超出整型范围,你只需输出...
  • nka_kun
  • nka_kun
  • 2018-04-02 14:42:27
  • 272

2018年第九届蓝桥杯省赛C++B组和javaB组题目

  • 2018年04月05日 11:52
  • 135KB
  • 下载

2018年第九届蓝桥杯【C++省赛B组】【题目汇总】

2018年第九届蓝桥杯【C++省赛B组】【题目汇总】 第一题:第几天 第二题:明码 第三题:乘积尾零 第四题:测试次数 第五题:快速排序 第...
  • qq_34202873
  • qq_34202873
  • 2018-04-02 09:36:59
  • 2368

20180401第九届蓝桥杯省赛B组真题-1第几天

标题:第几天2000年的1月1日,是那一年的第1天。那么,2000年的5月4日,是那一年的第几天?注意:需要提交的是一个整数,不要填写任何多余内容。手算都可以,这里直接粘贴2013年 高斯日记那道题了...
  • lady_killer9
  • lady_killer9
  • 2018-04-01 16:35:40
  • 1551

2018 蓝桥杯 省赛 B组 原题 C语言B组 第8题 第九届蓝桥杯真题 日志统计

标题:日志统计小明维护着一个程序员论坛。现在他收集了一份&quot;点赞&quot;日志,日志共有N行。其中每一行的格式是:ts id  表示在ts时刻编号id的帖子收到一个&quot;赞&quot;...
  • feifancaicai
  • feifancaicai
  • 2018-04-01 19:18:31
  • 374

2018省赛第九届蓝桥杯真题C语言B组

  • 2018年04月01日 16:49
  • 27KB
  • 下载

第九届蓝桥杯C/C++组真题B组

  • 2018年04月08日 08:58
  • 26KB
  • 下载

2018 蓝桥杯 省赛 B组 原题 C语言B组 第一题 第九届蓝桥杯真题 第几天 答案+解析+知识点

标题:第几天2000年的1月1日,是那一年的第1天。那么,2000年的5月4日,是那一年的第几天?注意:需要提交的是一个整数,不要填写任何多余内容。答案:125答案填空按要求写就Ok了思路1:笨方法按...
  • feifancaicai
  • feifancaicai
  • 2018-04-01 19:05:49
  • 736

2018 蓝桥杯 省赛 B组 原题 C语言B组 第3题 第九届蓝桥杯真题 +答案+解析

标题:乘积尾零如下的10行数据,每行有10个整数,请你求出它们的乘积的末尾有多少个零?5650 4542 3554 473 946 4114 3871 9073 90 4329 2758 7949 6...
  • feifancaicai
  • feifancaicai
  • 2018-04-01 19:10:13
  • 850

2018省赛第九届蓝桥杯真题C语言B组第六题题解 递增三元组

2018第九届蓝桥杯C++省赛B组[最新题解汇总]标题:递增三元组给定三个整数数组A = [A1, A2, ... AN], B = [B1, B2, ... BN], C = [C1, C2, .....
  • nka_kun
  • nka_kun
  • 2018-04-01 19:28:11
  • 215
    个人资料
    持之以恒
    等级:
    访问量: 1万+
    积分: 1353
    排名: 3万+
    最新评论