http://codeforces.com/contest/558/problem/C
每次操作 把a[i] ,/2取整或者X2,求min操作次数 使得所有的数一样
n和数的最大值 都是 1e5
这里 暴力枚举一下每个数字的情况即可
开一个vis[]
对于一个数x,每次/2都 做一轮 【 不断*2的操作 , 对于每次得到的一个数,vis[y]++,并且 step[y]+=步数】
这样就把每个数 所能变成的所有数,都枚举出来了,并且记下最早出现的那个步数
最后遍历一次1-maxn, 找到出现次数为n的 数中 所用步数最少的
一开始枚举每个数的所有情况时,用了set判重。。。TLE。。。。换成数组就78MS了.....
看来还是。。。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <set>
using namespace std;
__int64 ss[100005];
__int64 mark[111144*2];
__int64 vis[111144*2];
__int64 vis_num[111144*2];
int main()
{
__int64 n,i;
scanf("%I64d",&n);
for (i=1;i<=n;i++)
{
scanf("%I64d",&ss[i]);
}
__int64 ppp=100000;__int64 k;
for (k=1;k<=n;k++)
{
int cun=0;
__int64 tt=ss[k];
while(tt)
{
vis[tt]++;
mark[tt]+=cun;
vis_num[tt]=k;
__int64 tmp=tt;
int tmp_cun=cun;
while((tmp<<1)<=ppp)
{
tmp_cun++;
tmp<<=1;
if (vis_num[tmp]==k) break;
vis[tmp]++;
mark[tmp]+=tmp_cun;
vis_num[tmp]=k;
}
tt>>=1;
cun++;
}
}
__int64 minn=922337036854775807;
for (i=1;i<=100000;i++)
{
if (vis[i]!=n) continue;
if (mark[i]<minn)
minn=mark[i];//,printf("%I64d--%I64d\n",mark[i],i);
}
printf("%I64d\n",minn);
return 0;
}