标题:乘积最大
给定N个整数A1, A2, ... AN。请你从中选出K个数,使其乘积最大。
请你求出最大的乘积,由于乘积可能超出整型范围,你只需输出乘积除以1000000009的余数。
注意,如果X<0, 我们定义X除以1000000009的余数是负(-X)除以1000000009的余数。
即:0-((0-x) % 1000000009)
【输入格式】
第一行包含两个整数N和K。
以下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
资源约定:
峰值内存消耗(含虚拟机) < 256M
CPU消耗 < 1000ms
思路:这题我觉得贪心分情况即可:先按照绝对值从大到小排序
①假如选的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; }