Chemistry

Problem A. Chemistry

Input file: chemistry.in

Output file: chemistry.out

Time limit: 1 seconds

Memory limit: 256 megabytes

香香手中有n瓶化学药剂,每瓶化学药剂都有一个能量值ai。现在她想把这些药剂的能量值全部变成一样的,她有两台机器,其中一台机器一次可以把一瓶药剂的能量值翻倍,ai变成2ai,另一台机器一次可以把一瓶药剂的能量值变为一半,ai变成

然而每台每次启动都需要单位1的能量,她所储存的能量不多了,请你帮她计算一下用最少的能量完成这个任务。

Input

第一行输入一个n(1 <= n <= 10^5 )

第二行输入n个数,用空格隔开,表示每瓶药剂的能量值ai

(1 <= ai <= 10^5)

Output

输出一行,表示最少需要的能量值是多少。

Sample test(s)

input

3
4 8 2

output

2

input

3
3 5 6

output

5

样例解释:

第一个样例能量值全部为成4 ,第二个样例全部变为1

范围:

对于10% , n = 2

对于30% , n <= 100

对于另10% , ai <= 1000

对于100% , n <= 10^5 , ai <= 10^5

 

  分析:

  明显的DP,f[i][j]表示前i个数全部变成j所要耗费的能量,然后就是各种优化。。。。。

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstdlib>
  4 #include<algorithm>
  5 #include<cstring>
  6 #include<cmath>
  7 using namespace std;
  8 const int MAX=100005;
  9 const int inf=0x3f3f3f3f;
 10 int a[MAX];
 11 int b[MAX],b2[MAX];
 12 int c[10000000];
 13 int f[10][1000000];
 14 int may[1000000];
 15 int N;
 16 int ANS=inf;
 17 int MIN;
 18 int main(){
 19 //    freopen("chemistry.in","r",stdin);
 20 //    freopen("chemistry.out","w",stdout);
 21     scanf("%d",&N);
 22     for(int i=1;i<=N;i++) scanf("%d",&a[i]);
 23     sort(a+1,a+N+1);
 24     for(int i=1;i<=N;i++) b[i]=a[i],b2[i]=a[i];
 25     
 26     for(int i=1;i<=N;i++){//筛出来可能存在的数字 
 27         may[b[i]]++;
 28         
 29         while(b[i]*2<=4*a[N]){
 30             may[b[i]*2]++;
 31             b[i]*=2;
 32         }
 33         while(b2[i]/2>=1){
 34             may[b2[i]/2]++;
 35             b2[i]/=2;
 36         }
 37         
 38     }
 39     
 40     int now=0;
 41     for(int i=1;i<=4*a[N];i++){
 42         if(may[i]==N){//不为偶数的 
 43             now++;
 44             c[now]=i;    
 45         }
 46     }
 47     
 48     for(int k=1;k<=4*a[N]; ){
 49         if(may[k]!=N){
 50             now++;
 51             c[now]=k;
 52         }
 53         k<<=1;
 54     }
 55     //f[i][j]表示前i个数,全部变成c[j]时,所需的能量 
 56 
 57     for(int j=1;j<=now;j++){
 58         for(int i=1;i<=N;i++){//DP
 59             int num=c[j];
 60             int ans=0;
 61             
 62             if(may[num]==N){//序列中的每个数都可以直升直降得到 
 63             
 64                 if(num==a[i]) ans=0;
 65                 if(num>a[i]){
 66                     int x=a[i];
 67                     while(x!=num){
 68                         x*=2;
 69                         ans++;
 70                     }
 71                 }
 72                 if(num<a[i]){
 73                     int x=a[i];
 74                     while(x!=num){
 75                         x/=2;
 76                         ans++;
 77                     }
 78                 }
 79             }
 80             //*********
 81             else{//有的数字必须先降再升可以达到 
 82                 int x=a[i];
 83                 if(num==a[i]) ans=0;
 84                 if(num>a[i]){
 85                     while(x!=num){
 86                         x<<=1;
 87                         ans++;
 88                         if(x>num){
 89                             ans=inf;
 90                             break;
 91                         }
 92                     }
 93                 }
 94                 if(ans==0&&num!=a[i]) 
 95                     ans=inf;
 96                 if(x!=num){
 97                     int ans1=0;
 98                     int x=a[i];
 99                     while(x!=1){
100                         if(x==num) break;
101                         else{
102                             x>>=1;
103                             ans1++;
104                         }
105                     }
106                     while(x!=num){
107                         x<<=1;
108                         ans1++;
109                     }
110                     ans=min(ans,ans1);
111                 }    
112             }
113             f[2][j]=f[1][j]+ans;
114             f[1][j]=f[2][j];
115             f[2][j]=0;
116             if(i==N) 
117                 ANS=min(ANS,f[1][j]);
118         }
119     }
120 
121     cout<<ANS;
122     return 0;
123 }

 

 

原文地址:https://www.cnblogs.com/CXCXCXC/p/4716185.html