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

来源:互联网 发布:手机散热软件 编辑:程序博客网 时间:2024/05/29 07:54

题目地址

题目大意:给出n个数,每次操作可以对其中一个数进行乘以2操作或者除以2操作,求将n个数变成同一个数所需要的最少的操作步数

解题思路:乘以2/除以2,相当于右移/左移,对于每个数枚举其可以变成的数及其最小步数,最后再看是否所有的数都能变成该数,再比较是否为最小的。在枚举的过程中,需要注意一直左移可得到比其大的数,右移过程中若遇到奇数,就需要将其减去1的数进行左移,那些数也是可以由该数变成的,另,需要注意右移的过程中,需要从本身开始,遇到奇数执行减1左移操作

#include <bits/stdc++.h>using namespace std;const int maxn = 1e5+100;int a[maxn],res[maxn],vis[maxn];int main(){    int n;    while(scanf("%d",&n) != EOF)    {        memset(res,0,sizeof(res));        memset(vis,0,sizeof(vis));        int maxx = 0;        for(int i = 0; i < n; i++)        {            scanf("%d",&a[i]);            maxx = max(maxx,a[i]);        }        for(int i = 0; i < n; i++)        {            int cnt = 1;            for(int j = a[i]<<1; j <= maxx; j <<= 1)            {                    vis[j]++;                    res[j] += cnt;                    cnt++;            }            cnt = 0;            for(int j = a[i]; j >= 1; j >>= 1)            {                vis[j]++;                res[j] += cnt;                cnt++;                if(j&1 && j != 1)                {                    int cntt = cnt+1;                    for(int k = j-1; k <= maxx; k <<= 1)                    {                        vis[k]++;                        res[k] += cntt;                        cntt++;                     }                }            }        }        int minn = 0xffffff;        for(int i = 1; i <= maxx; i++)            if(vis[i]==n)                minn = min(minn,res[i]);        printf("%d\n",minn);    }return 0;}



0 0
原创粉丝点击