CodeForces 558 C. Amr and Chemistry && 51NOD 1483 化学变换(暴力 + 贪心)

传送门

Amr loves Chemistry, and specially doing experiments. He is preparing for a new interesting experiment.

Amr has n different types of chemicals. Each chemical i has an initial volume of ai liters. For this experiment, Amr has to mix all the chemicals together, but all the chemicals volumes must be equal first. So his task is to make all the chemicals volumes equal.

To do this, Amr can do two different kind of operations.

Choose some chemical i and double its current volume so the new volume will be 2ai

Choose some chemical i and divide its volume by two (integer division) so the new volume will be

Suppose that each chemical is contained in a vessel of infinite volume. Now Amr wonders what is the minimum number of operations required to make all the chemicals volumes equal?

Input

The first line contains one number n (1?≤?n?≤?105), the number of chemicals.

The second line contains n space separated integers ai (1?≤?ai?≤?105), representing the initial volume of the i-th chemical in liters.

Output

Output one integer the minimum number of operations required to make all the chemicals volumes equal.

Examples

input

3

4 8 2

output

2

input

3

3 5 6

output

5

Note

In the first sample test, the optimal solution is to divide the second chemical volume by two, and multiply the third chemical volume by two to make all the volumes equal 4.

In the second sample test, the optimal solution is to divide the first chemical volume by two, and divide the second and the third chemical volumes by two twice to make all the volumes equal 1.

题目大意:

有n种不同的化学试剂。第i种有ai升。每次实验都要把所有的化学试剂混在一起,但是这些试剂的量一定要相等。所以现在的首要任务是把这些化学试剂的量弄成相等。

有两种操作:

· 把第i种的量翻倍,即第i种的量变成2ai。

· 把第i种的量减半,除的时候向下取整,即把第i种的量变成 ? ai/2 ? 。

现在所有的化学试剂的量已知,问最少要变换多少次,这些化学试剂的量才会相等。

样例解释:把8变成4,把2变成4。这样就需要两次就可以了。

解题思路:

我们可以进行一次初始化,也就是枚举出每个数能够到达的数字并且记录到达该数字需要的步数,然后从到达次数为 n 次的数字中选择步数最小的就是我们所要求的。因为我们可以通过乘以2或者除以2来得到我们想要得到的数,如果是奇数的话就得先除以2,然后一直乘以2直到达到最大值。用两个数组分别记录,vis[]记录由几个数转化而来,step[]记录这个数由多少卟转化而来,最后找到vis[i]==n 的值,然后取step[]最小的值输出即可。

My Code:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int MAXN = 1e6+5;
const int INF = 0x3f3f3f3f;
int step[MAXN], vis[MAXN], Max;
void Init(int x)
{
    int tmp1 = x, tmp2 = x, tmp3 = 0;
    int step1 = 0, step2 = 0, step3 = 0;
    while(1)
    {
        if(tmp1 > Max)
            break;
        tmp1<<=1;
        vis[tmp1]++;
        step1++;
        step[tmp1] += step1;
    }
    while(tmp2)
    {
        if(tmp2&1 && tmp2!=1)
        {
            tmp2>>=1;
            vis[tmp2]++;
            step2++;
            step[tmp2] += step2;
            tmp3 = tmp2;
            step3 = step2;
            while(1)
            {
                if(tmp3 > Max)
                    break;
                tmp3<<=1;
                vis[tmp3]++;
                step3++;
                step[tmp3] += step3;
            }
        }
        else
        {
            tmp2>>=1;
            vis[tmp2]++;
            step2++;
            step[tmp2] += step2;
        }
    }
}
int a[MAXN];
int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        Max = -1;
        memset(vis, 0, sizeof(vis));
        memset(step, 0, sizeof(step));
        for(int i=0; i<n; i++)
        {
            scanf("%d",&a[i]);
            vis[a[i]] = 1;
            if(Max < a[i])
                Max = a[i];
        }
        for(int i=0; i<n; i++)
            Init(a[i]);
        int ans = INF;
        for(int i=1; i<=Max*2; i++)
        {
            if(vis[i] == n)
            {
                if(step[i] < ans)
                    ans = step[i];
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}
时间: 2024-10-30 08:20:25

CodeForces 558 C. Amr and Chemistry && 51NOD 1483 化学变换(暴力 + 贪心)的相关文章

codeforces 558 C Amr and Chemistry

预处理两个数组: vis[x],有几个数能够变成x num[x],所有数变成x最少需要变化的步数 ans=min(num[x]),vis[x]==n #include<map> #include<string> #include<cstring> #include<cstdio> #include<cstdlib> #include<cmath> #include<queue> #include<vector>

CF 558 C. Amr and Chemistry 暴力+二进制

链接:http://codeforces.com/problemset/problem/558/C C. Amr and Chemistry time limit per test 1 second memory limit per test 256 megabytes input standard input output standard output Amr loves Chemistry, and specially doing experiments. He is preparing

暴力 + 贪心 --- Codeforces 558C : Amr and Chemistry

C. Amr and Chemistry Problem's Link: http://codeforces.com/problemset/problem/558/C Mean: 给出n个数,让你通过下面两种操作,把它们转换为同一个数.求最少的操作数. 1.ai = ai*2 2.ai = ai/2 (向下取整) analyse: 基本思路:首先枚举出每个数能够到达的数字并且记录下到达该数组需要的步数,然后从到达次数为n次的数字中选择步数最小的即为答案. 对于一个数字Ai,它可以变换得到的数字可

Codeforces Round #312 (Div. 2) C.Amr and Chemistry

Amr loves Chemistry, and specially doing experiments. He is preparing for a new interesting experiment. Amr has n different types of chemicals. Each chemical i has an initial volume of ai liters. For this experiment, Amr has to mix all the chemicals

Codeforces Round #312 (Div. 2)——C暴力技巧——Amr and Chemistry

Amr loves Chemistry, and specially doing experiments. He is preparing for a new interesting experiment. Amr has n different types of chemicals. Each chemical i has an initial volume of ai liters. For this experiment, Amr has to mix all the chemicals

Codeforces 558C Amr and Chemistry(数论+位运算)

C. Amr and Chemistry time limit per test 1 second memory limit per test 256 megabytes input standard input output standard output Amr loves Chemistry, and specially doing experiments. He is preparing for a new interesting experiment. Amr has n differ

Codeforces Round #243 (Div. 2) C. Sereja and Swaps(优先队列 暴力)

题目 题意:求任意连续序列的最大值,这个连续序列可以和其他的 值交换k次,求最大值 思路:暴力枚举所有的连续序列.没做对是因为 首先没有认真读题,没看清交换,然后,以为是dp或者贪心 用了一下贪心,各种bug不对. 这次用了一下优先队列,以前用的不多,看这个博客又学了一下 AC代码: 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 #i

Codeforces Round #286 (Div. 2)A. Mr. Kitayuta&#39;s Gift(暴力,string的应用)

由于字符串的长度很短,所以就暴力枚举每一个空每一个字母,出现行的就输出.这么简单的思路我居然没想到,临场想了很多,以为有什么技巧,越想越迷...是思维方式有问题,遇到问题先分析最简单粗暴的办法,然后一步一步的优化,不能盲目的想. 这道题要AC的快需要熟悉string的各种用法.这里做个简单总结:C++中string的常见用法. #include<iostream> #include<cstdio> #include<cstdlib> #include<cstrin

CodeForces 558C Amr and Chemistry (位运算,数论,规律,枚举)

Codeforces 558C 题意:给n个数字,对每个数字可以进行两种操作:num*2与num/2(向下取整),求:让n个数相等最少需要操作多少次. 分析: 计算每个数的二进制公共前缀. 枚举法亦可. /* *Author : Flint_x *Created Time : 2015-07-22 12:33:11 *File name : whust2_L.cpp */ #include<iostream> #include<sstream> #include<fstrea