hdu 4038 模拟+贪心 Stone
2012-08-29 14:17
393 查看
题意:
给一个数列,可以对这数列进行两种操作:A.使其中的一个数加1;B.增加1到这个数列。要求这个数列的乘积最大。
思路:贪心+模拟。
我觉得不够清晰。再理一遍。
1. 负数个数为奇数的时候我们把最大的负数变成0;
2.0是我们在这题当中很讨厌的东西(其他题也有卡0的,比如0!= 1,1对1的逆元是0),所以我们先将所有的精力集中对付0。
3.当0没有了的时候,我们其次讨厌1。为什么呢,因为1->2是2倍的收益,相对其他的数以及其他的添加1的操作来说,她用1的收益最大。我们要得到最大收益,所以,把1全部变成2。
4.没有1,0的时候,我们把2全部变成3。是3/2的收益。
5.没有2,1,0的时候,我们是不是要把所有的3变成4呢?不是的。为什么这里就不是,上面就是呢?是这样的。当操作m=2时,我们用这两个二将两个1变成2收益是4 > 2,将两个2变成3收益是1.5*1.5 > 2,将两个3变成4的收益是1.333333*1.333333 = 1.777777 < 2,还不如将这两个一加在一起变成2加到原来的序列里面;当m=3时,我们用这3个二将3个1变成2收益是8 > 3,将3个2变成3收益是1.5*1.5
*1.5 > 3,将两个3变成4的收益是1.333333*1.333333 * 1.333333 < 3;以此类推。
6.由以上推得,做完以上操作之后如果m = 1,则加到最小的那个非负数上;m>1时,如果m%3==0,则加m / 3个3就行;(m - 1) % 3 == 0时,加(m-1)/3 - 1个3,再加个4;(m - 2) % 3 == 0,加(m - 2)/3个3,再加个2。
到此,终于完了。。。。
做题过程:
将思路理清楚之后就容易了,调了一会,1A。
给一个数列,可以对这数列进行两种操作:A.使其中的一个数加1;B.增加1到这个数列。要求这个数列的乘积最大。
思路:贪心+模拟。
我觉得不够清晰。再理一遍。
1. 负数个数为奇数的时候我们把最大的负数变成0;
2.0是我们在这题当中很讨厌的东西(其他题也有卡0的,比如0!= 1,1对1的逆元是0),所以我们先将所有的精力集中对付0。
3.当0没有了的时候,我们其次讨厌1。为什么呢,因为1->2是2倍的收益,相对其他的数以及其他的添加1的操作来说,她用1的收益最大。我们要得到最大收益,所以,把1全部变成2。
4.没有1,0的时候,我们把2全部变成3。是3/2的收益。
5.没有2,1,0的时候,我们是不是要把所有的3变成4呢?不是的。为什么这里就不是,上面就是呢?是这样的。当操作m=2时,我们用这两个二将两个1变成2收益是4 > 2,将两个2变成3收益是1.5*1.5 > 2,将两个3变成4的收益是1.333333*1.333333 = 1.777777 < 2,还不如将这两个一加在一起变成2加到原来的序列里面;当m=3时,我们用这3个二将3个1变成2收益是8 > 3,将3个2变成3收益是1.5*1.5
*1.5 > 3,将两个3变成4的收益是1.333333*1.333333 * 1.333333 < 3;以此类推。
6.由以上推得,做完以上操作之后如果m = 1,则加到最小的那个非负数上;m>1时,如果m%3==0,则加m / 3个3就行;(m - 1) % 3 == 0时,加(m-1)/3 - 1个3,再加个4;(m - 2) % 3 == 0,加(m - 2)/3个3,再加个2。
到此,终于完了。。。。
做题过程:
将思路理清楚之后就容易了,调了一会,1A。
#include <iostream> #include <cstdio> #include <algorithm> #define mod 1000000007 using namespace std; int t,n,a[100010],odd_num,m,indx,Minpos,Min; __int64 ans; void init(){ odd_num = 0; ans = 1; Min = mod; indx = 1;//初始化!!! } long long pow_mod(int a,int n,int p) { long long ret=1; long long A=a; while(n) { if (n & 1) ret=(ret*A)%p; A=(A*A)%p; n>>=1; } return ret; } int main() { scanf("%d",&t); for(int ca = 1; ca <= t; ca ++){ scanf("%d%d",&n,&m); init(); for(int i = 1; i <= n;i ++){ scanf("%d",a + i); if(a[i] < 0) odd_num++; } sort(a + 1, a + 1 + n); if(odd_num & 1){//负数个数为奇数的时候,去改最大的负数 int j = 1; while(a[j] < 0) j ++; indx = -- j;// // cout << "j" << j << endl; if(a[j] + m > 0) m += a[j], a[j] = 0; else a[j] += m,m = 0; } if(m > 0){ // for(int j = 1; j <= n - 1; j ++) // printf("%d ",a[j]); printf("%d\n",a ); // cout << indx << endl; for(int j = indx; j <= n && m > 0; j ++) if(a[j] == 0) a[j] ++, m --; for(int j = indx; j <= n && m > 0; j ++) if(a[j] == 1) a[j] ++, m --; for(int j = indx; j <= n && m > 0; j ++) if(a[j] == 2) a[j] ++, m --; // for(int j = 1; j <= n - 1; j ++) // printf("%d ",a[j]); printf("%d\n",a ); for(int j = 1; j <= n; j ++) ans = (ans * a[j]) % mod; if(m <= 0){ printf("Case %d: %I64d\n",ca,ans); }else{ if(m == 1){ for(int j = 1; j <= n; j ++) if(Min > a[j]) Min = a[j], Minpos = j; ans /= a[Minpos]; ans = (ans * (a[Minpos] + 1)) % mod; printf("Case %d: %I64d\n",ca,ans); }else if(m % 3 == 0){ ans = (ans * pow_mod(3,m/3,mod)) % mod; printf("Case %d: %I64d\n",ca,ans); }else if((m - 1) % 3 == 0){ ans = (ans * pow_mod(3,(m - 1)/3 - 1,mod)) % mod; ans = (ans * 4) % mod; printf("Case %d: %I64d\n",ca,ans); }else if((m - 2) % 3 == 0){ ans = (ans * pow_mod(3,(m - 2)/3,mod)) % mod; ans = (ans * 2) % mod; printf("Case %d: %I64d\n",ca,ans); } } } else{ for(int j = 1; j <= n; j ++) ans = (ans * a[j]) % mod; printf("Case %d: %I64d\n",ca,ans); } } return 0; }
相关文章推荐
- hdu 4038 Stone(贪心模拟)
- Stone----HDU_4308----模拟+贪心+一点点二分的思想
- HDU 4038 Stone (模拟 快速幂)
- HDU 4038 Stone(11年成都网络赛-H题-贪心)
- hdu 5920 贪心+模拟
- 贪心,模拟,构造(HDU 5414,CRB and String)
- hdu 4038 2011成都赛区网络赛H 贪心 ***
- hdu 3573 贪心 + 模拟
- hdu 6237 A Simple Stone Game (求素因子+贪心)
- HDU-新生赛-游乐场【模拟+贪心】
- hdu 5920 贪心+模拟
- HDU 1355 贪心模拟
- 【JZOJ3819】【NOI2015模拟9.9】【hdu 4111】取石子(博弈+贪心+记忆化搜索)
- HDU 4708 Rotation Lock Puzzle (贪心+模拟)
- HDU 5246 超级赛亚ACMer(贪心模拟)
- HDU 4023 (博弈 贪心 模拟) Game
- 1/21集训二 模拟+贪心 G.(贪心 安排做作业的时间)Doing Homework again(感觉有点像HDU安排电视节目的那题(今年暑假不AC))
- hdu 4038 Stone
- hdu 5920 贪心+模拟
- 【贪心】【模拟】HDU 5491 The Next (2015 ACM/ICPC Asia Regional Hefei Online)