HDU4038-Stone(思维题)

来源:互联网 发布:魔兽世界哪些插件软件 编辑:程序博客网 时间:2024/04/29 07:23

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
41 153 21 2 33 2-1 2 33 1-3 -3 -3
 

Sample Output
Case 1: 6Case 2: 18Case 3: 6Case 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;}




0 0
原创粉丝点击