题目链接:codeforces558C
位运算,加暴力,将每个数乘除所得数求出来,当所有数枚举到n,并且步数最小即可。
注意:
当a为奇数时,a除以2,再乘以2,得不到a,所以此时a向下遍历(除以2)时,所得数向上遍历会得到新的数,那么在a向下遍历时,若得到的数是奇数,则对该数进行一次向上遍历的操作。(该过程为代码中开始结束部分)
<pre name="code" class="cpp">#define _CRT_SECURE_NO_DEPRECATE
#include<stdio.h>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn = 100000 + 10;
int visit[maxn * 2], cnt[maxn * 2];
void dfs(int a){
int tmpup = a, tmpdown = a, stepup = 0, stepdown = 0;
while (tmpup <= int(1e5)){
visit[tmpup]++;
cnt[tmpup] += stepup;
tmpup <<= 1;
stepup++;
}
//开始
while (tmpdown){
if ((tmpdown & 1) && tmpdown != 1){
tmpdown >>= 1;
stepdown++;
visit[tmpdown]++;
cnt[tmpdown] += stepdown;
int stepup2 = stepdown;
int tt = tmpdown;
while (tt <= 1e5){
tt <<= 1;
visit[tt]++;
stepup2++;
cnt[tt] += stepup2;
}
}
else{
tmpdown >>= 1;
stepdown++;
visit[tmpdown]++;
cnt[tmpdown] += stepdown;
}
}
//结束
}
int main(){
int n;
while (scanf("%d", &n) != EOF){
memset(visit, 0, sizeof(visit));
memset(cnt, 0, sizeof(cnt));
int a;
for (int i = 0; i < n; i++){
scanf("%d", &a);
dfs(a);
}
int ans = 99999999;
for (int i = 0; i < (int)(2 * 1e5); i++){
if (visit[i] == n)
ans = min(ans, cnt[i]);
}
printf("%d\n", ans);
}
return 0;
}