codeforces Round #670 (Div. 2) 1406B Maximum Product

题目链接

在这里插入图片描述

题目翻译:

给你一个数列a1,a2,…,an。找出五个下标i, j, k, l, t (i<j<k<l<t)使得aiajakalat 最大。

解题思路:

首先我们要根据最后结果是正还是负进行讨论。如果所有数都是负数,那么最后的结果肯定是负数,因此我们要输出最大五个数的积;如果所有的数不是负数就是0,我们直接输出0就可以了;最后一种情况就是有正有负有0,首先我们要知道,如果这五个数的积是负数,只要替换其中一个数(正数换成负数或者负数换成正数),就可以让积变成正数,或者将其中一个数换成0,使积变成0。因此,我们要先将所有数字按绝对值从大到小进行排序,取最大的五个数,如果是正数,那肯定就是最大值了(绝对值最大,又是正数,当然最大),如果是负数,我们可以替换其中一个数,使积变成非负数(且得到的积会是尽可能大的)。

代码:
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
const int N = 100010;
int t,n,a[N],maxn = INT_MIN;
bool mysort(int a,int b){
    
    
	return abs(a)>abs(b);
}
int main(){
    
    
//	freopen("1.txt","r",stdin);
	cin>>t;
	while(t--){
    
    
		cin>>n;
		maxn = INT_MIN;//找到最大值
		for(int i=0;i<n;i++){
    
    
			cin>>a[i];
			maxn = max(maxn,a[i]);
		}
		sort(a,a+n,mysort);
		//如果所有数都是非正数,输出绝对值最小的5个数
		if(maxn<=0){
    
    
			cout<<(long long)a[n-1]*a[n-2]*a[n-3]*a[n-4]*a[n-5]<<endl;
			continue;
		}
		long long ans = (long long)a[0]*a[1]*a[2]*a[3]*a[4];
		//如果结果为0,直接输出。表示正负数的个数不足5个
		if(ans==0){
    
    
			cout<<0<<endl;
			continue;
		}
		for(int i=0;i<5;i++){
    
    
			//去除五个数中的一个数
			long long tmp = (long long)a[0]*a[1]*a[2]*a[3]*a[4]/a[i];
			for(int j=5;j<n;j++){
    
    
				//用剩余数中的数代替,比较最大值
				ans = max(ans,(long long)tmp*a[j]);
			}
		}
		cout<<ans<<endl;
	}
	return 0;
}
我的思路:

同样,如果所有的数都是负数,结果就是最大五个数的积;如果只有负数和0,结果就是0;如果既有正数又有负数和0,则需要进一步判断。我发现如果要让五个数的积为正,则五个数中负数的个数必须是偶数个,所以如果sumn/2*2+sump>=5&&sump>0,则表示结果一定为正,其中sumn表示负数的个数,sump表示正数的个数。其中sumn/2*2表示负数的最大偶数个数,即保证负数被计算在内的必须是偶数个,满足条件的数必须大于等于5个,且正数的个数至少为1。否则结果为非正数。现在的问题是怎么计算出最终的结果,首先肯定有一个正数,所以我们直接把最大的正数作为第一个数,然后再根据绝对值从大到小取两对正数或负数。

代码:
#include<iostream>
#include<cstring>
#include<algorithm>
#include<vector>
#include<cmath>
using namespace std;
vector<long long>vp,vn,v;
const int N = 100010;
long long t,n,a[N];
bool mysort(long long a,long long b){
    
    
	return a>b;
}
bool mysort2(long long a,long long b){
    
    
	return abs(a)<abs(b);
}
int main(){
    
    
//	freopen("1.txt","r",stdin);
	cin>>t;
	while(t--){
    
    
		cin>>n;
		vp.clear(),vn.clear(),v.clear();
		int sump=0,sumn=0,sum0=0;
		long long sum=1;
		for(int i=0;i<n;i++){
    
    
			cin>>a[i];
			if(a[i]>0){
    
    
				vp.push_back(a[i]);
			}else if(a[i]<0){
    
    
				vn.push_back(a[i]);
			}else{
    
    
				sum0++;
			}
		}
		sump=vp.size(),sumn=vn.size();
		//正 
		if(sumn/2*2+sump>=5&&sump>0){
    
    
			sort(vp.begin(),vp.end(),mysort);
			sort(vn.begin(),vn.end());
			sum*=vp[0];
			for(int i=1;i+1<vp.size();i+=2){
    
    
				v.push_back(vp[i]*vp[i+1]);
			}
			for(int i=0;i+1<vn.size();i+=2){
    
    
				v.push_back(vn[i]*vn[i+1]);
			}
			sort(v.begin(),v.end(),mysort);
			sum=sum*v[0]*v[1];
			cout<<sum<<endl;
		}else if(sum0!=0){
    
    
			cout<<0<<endl;
		}else{
    
    //负 
			sort(a,a+n,mysort2);
			sum=a[0]*a[1]*a[2]*a[3]*a[4];
			cout<<sum<<endl;
		}
	}
	return 0;
}
总结:

错了两次,因为没注意数据类型。下次该多看两眼。

猜你喜欢

转载自blog.csdn.net/lmmmmmmmmmmmmmmm/article/details/108600805