HDU4038-Stone(思维题)

Stone

Time Limit: 3000/2000 MS (Java/Others)    Memory Limit: 65768/65768 K (Java/Others)
Total Submission(s): 2267    Accepted Submission(s): 568


Problem Description
Given an array of integers {xi}. Each time you can apply one of the following operations to the array:
1. Choose an integer x from the array, replace it with x+1.
2. Add a new integer 1 to the array.

Define p as the product of all integers in the set. i.e. p=x1*x2*x3*...
What's the maximum possible value of p after exactly M operations?
 

Input
First line is a integer T (T ≤ 100), the number of test cases.
The first line of each test case contains two integers N and M, the number of integers in the initial set, and the number of operations.
The second line is N integers xi initially in the set.
1 ≤ N ≤ 100000
0 ≤ M ≤ 10^18
-10000 ≤ xi ≤ 10000
 

Output
For each case, you should output “Case k: ” first, where k indicates the case number and counts from one. Then the maximum product mod 1000000007.
 

Sample Input
  
  
4 1 1 5 3 2 1 2 3 3 2 -1 2 3 3 1 -3 -3 -3
 

Sample Output
  
  
Case 1: 6 Case 2: 18 Case 3: 6 Case 4: -18
 
题意:有n个数(n<=1e5),m次操作(m<=1e18),每次操作,可以将某一个数加1,也可以放1个1到原数列中,问操作完后,n个数的乘积最大是多少?

思路:分类讨论:
一.先看负数的奇偶性:
1.如果是奇数,那么看最小的负数的绝对值如果大于m那么答案就是将这个数加上m然后直接算乘积(因为这个时候选择增长的倍率每步都是最高的)。否则的话就将这个数变成0,然后就与2相同了.
2. 如果是偶数,那么,就像将当中的0变成1,因为此时的性价比最高,因为这时候乘积从0变成了整数,接下来就是把所有的1变成2,那么就会有其他选择,如现将1都变
成3,此时2步的增长率是3,而前者的2步的增长率4,是最高的。接下来就是把所有的2变成3,如果将2变成4,此时2步的增长率是2,而前者是9/4,性价比是最高的。(你如果这时候在处理负数的话,整个乘积更是再减少!)
二.这个时候只剩下大于等于3的正整数了(前提是m还是正的),这个时候就要考虑添1的性价比了,考虑到只添1是没有意义的,至少要添1加上1,添1加1的相当于2步的增长率为2,而如果你用这两步处理3的话,25/16 和 5/3明显要劣于添1加1,接下来的就是讨论花两步变成2,和花3步变成3哪个性价比高了, 就是比较 2^(m/2)和3^(m/3) ,
1.m是3的倍数,那么明显是后者高。
2.如果m%3 = 1,那么(m-4)是3的倍数,2^(m-4)/2小于 3^(m-4)/3, 剩下的4,明显2^2 > 3^4/3,也可以是(m-1)/3,此时的增长率是 3^(m-1)/3还有1个1,此时的选择是添1,或者给某个3加上1,那么和前者有什么区别? 
3.如果m%3 = 2,那么(m-2)是3的倍数,2^(m-2)/2小于3^(m-2)/3,剩下的2,明显明显2^2/2 > 3^4/3,也可以是分别给2个3加上1,那么此时的增长率是 16/9,低于前者。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
using namespace std;
typedef long long ll;
const int maxn = 100000+10;
const int MOD = 1000000007;
const int inf = 1e9;
int num[maxn];
int n;
ll m;
int neg_cnt;
ll ans;

ll pow_mod(ll n,ll m){
	ll ret = 1,tmp = n;
	while(m>0){
		if(m&1) ret = (ret*tmp)%MOD;
		tmp = (tmp*tmp)%MOD;
		m>>=1;
	}
	return ret;
}
void init(){
	ans = 1;
	neg_cnt = 0;
}
void input(){
	scanf("%d%I64d",&n,&m);
	for(int i = 0; i < n; i++){
		scanf("%d",&num[i]);
		if(num[i]<0) neg_cnt++;
	}
	sort(num,num+n);
}
void output(){
	for(int i = 0; i < n; i++){
		ans = (ans*num[i])%MOD;
	}
	printf("%I64d\n",ans);
	
}
void compute(){
	for(int i = 0; i < n && m>0; i++){
		if(num[i]==0){
			++num[i];
			--m;
		}
	}
	for(int i = 0; i < n && m >0; i++){
		if(num[i]==1){
			++num[i];
			--m;
		}
	}
	for(int i = 0; i < n && m > 0; i++){
		if(num[i]==2){
			++num[i];
			--m;
		}
	}
	ll cnt_3;
	if(m >= 2){
		if(m%3==0){
			cnt_3 = m/3;
			ans = pow_mod((ll)3,cnt_3);
		}else{
			int remain = m%3;
			if(remain==1){
				cnt_3 = m/3-1;
				ans = pow_mod((ll)3,cnt_3);
				ans = (ans*4)%MOD;	
			}else{
				cnt_3 = m/3;
				ans = pow_mod((ll)3,cnt_3);
				ans = (ans*2)%MOD;
			}
		}
	}
	if(m==1){
		int absMin = inf,minIdx = 0;
		for(int i = 0; i < n; i++){
			if(num[i] != -1){
				if(absMin > abs(num[i])){
					absMin = abs(num[i]);
					minIdx = i;
				}
			}
		}
		num[minIdx]++;
	}
	output();
	
}
void solve(){
	if(neg_cnt&1){
		int k = 0;
		while(k<n&&num[k]<0) k++;
		--k;
		if(m+num[k]<=0){
			num[k] += m;
			output();
		}else{
			m += num[k];
			num[k] = 0;
			compute();
		}
	}else{
		compute();
	}
	
}
int main(){
	
	int ncase,T=1;
	cin >> ncase;
	while(ncase--){
		init();
		input();
		printf("Case %d: ",T++);
		solve();
	}	
	return 0;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值