AcWing 1239. 乘积最大

原题链接

考察:贪心

错误思路:

       将两个负数作为一个数纳入新数组排序,从大选到小.

这个思路错在如果存在两个负数的积比一个正数大,而两个正数的积又比负数积大,这样会答案错误.

思路:

        分类讨论

  1. k为偶数,正数和负数都必须两个两个选,这里运用到了双指针算法.此时选出的答案一定为正数.
  2. k为奇数,此时负数必须两个两个选.如果所有的数都为负数,那我们只从右边选; 如果存在一个正数,我们必须先选最大的正数,再两头选.

这里涉及一个技巧(常识) 所有数是否都为负数没必要全看一遍,看最大的就行了

这里的sign变量可以使得双指针算法选两头最小的

注意这道题,选两个数的时候,一定要看乘积而不是乘积%Mod,因为如果乘积是Mod倍数反而使得结果变小了.

 1 #include <iostream>
 2 #include <algorithm>
 3 #include <cstring>
 4 using namespace std;
 5 const int Mod = 1000000009,N = 100010;
 6 typedef long long LL;
 7 int n,k,a[N];
 8 int main()
 9 {
10     scanf("%d%d",&n,&k);
11     for(int i=1;i<=n;i++) scanf("%d",&a[i]);
12     sort(a+1,a+n+1);
13     LL ans = 1;
14     int r = n,l = 1,sign = 1;
15     if(k&1)
16     {
17         ans = a[r--];
18         k--;
19         if(ans<0) sign = -1;
20     }
21     while(k)
22     {
23         LL low = (LL)a[l]*a[l+1];
24         LL high = (LL)a[r]*a[r-1];
25         if(low*sign>sign*high) l+=2,ans = low%Mod*ans%Mod;
26         else  r-=2,ans = high%Mod*ans%Mod;
27         k-=2;
28     }
29     printf("%lld\n",ans);
30     return 0;
31 }

 

posted @ 2021-02-26 23:23  acmloser  阅读(56)  评论(0编辑  收藏  举报