AcWing 1239. 乘积最大
考察:贪心
错误思路:
将两个负数作为一个数纳入新数组排序,从大选到小.
这个思路错在如果存在两个负数的积比一个正数大,而两个正数的积又比负数积大,这样会答案错误.
思路:
分类讨论
- k为偶数,正数和负数都必须两个两个选,这里运用到了双指针算法.此时选出的答案一定为正数.
- 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 }