[ABC173E] Multiplication 4 题解
思路
首先注意到最好的情况就是有偶数个负数,否则算出来的乘积是负的,并不好。因此我们要极力避免选择奇数个负数的情况。
注意到当
关于零
注意到当
不存在任何正数
对于
对于
存在正数
考虑
对于
然后问题转变为选择乘积最大的
但是这样做是有问题的。注意到负数和正数的数量可能是奇数,因此最后可能会剩余
剩余
但是如果剩下的是
对于一般情况,选择乘积最大的 long long。
代码
#include <bits/stdc++.h>
#define ET return 0
#define fi first
#define se second
#define mp make_pair
#define pb emplace_back
#define ll long long
#define ull unsigned long long
#define inf INT_MAX
#define uinf INT_MIN
#define pii pair<int,int>
#define pll pair<ll,ll>
#define debug puts("--------Chery AK IOI--------");
#define Yes cout<<"Yes"<<endl;
#define No cout<<"No"<<endl;
#define pt puts("")
#define fr1(i,a,b) for(int i=a;i<=b;i++)
#define fr2(i,a,b) for(int i=a;i>=b;i--)
#define fv(i,p) for(int i=0;i<p.size();i++)
#define ld long double
#define il inline
#define ptc putchar
using namespace std;
int n,k;
vector <ll> pos,uos;
ll ans=1;
ll x;
int cnt;
const ll M=1e9+7;
vector <ll> up;
int main(){
cin>>n>>k;
fr1(i,1,n){
cin>>x;
ans*=x;
ans%=M;
if(x>0){
pos.pb(x);
}
else if(x<0){
uos.pb(x);
}
else{
cnt++;
}
}
if(cnt+k>n){//特判0太多了
cout<<"0"<<endl;
ET;
}
if(k==n){//特判k=n
cout<<(ans+M)%M<<endl;
ET;
}
sort(pos.begin(),pos.end());//正数从小到大排序
sort(uos.begin(),uos.end());//负数从小到大排序
if(pos.size()==0){//没有正数
ans=1;
if(k%2){
if(cnt){//有0就选择0
cout<<"0"<<endl;
ET;
}
reverse(uos.begin(),uos.end());//把负数反转过来,让绝对值小的数在前面
fr1(i,0,k-1){
ans*=uos[i];
ans%=M;
}
cout<<(ans+M)%M<<endl;
}
else{
fr1(i,0,k-1){//直接从绝对值大的开始选
ans*=-uos[i];
ans%=M;
}
cout<<ans%M<<endl;
}
}
else{
ans=1;
if(k%2){
ans=pos[pos.size()-1];//取走最大的正数
pos.pop_back();
k--;
}
reverse(pos.begin(),pos.end());//把正数反转过来,让绝对值大的数放在前面
fv(i,pos){
up.pb(pos[i]*pos[i+1]);
i++;
}
fv(i,uos){
up.pb(uos[i]*uos[i+1]);
i++;
}//两两分组
sort(up.begin(),up.end());
reverse(up.begin(),up.end());//让组按乘积从大到小排序
int l=0;
while(k){
ans*=up[l]%M;
ans%=M;
l++;
k-=2;
}//暴力选择前k/2个即可
cout<<ans<<endl;
}
ET;
}
AC 记录