http://codeforces.com/problemset/problem/558/C
分析:将每一个数在给定范围内(10^5)可变成的数(*2或者/2)都按照广搜的方式生成访问一遍,标记上访问的步数,之后遍历区间找到被访问次数达到n(所有数都可以变成这个数)并且标记的需要步数最少即可。
注意:当是奇数的时候,例如11(11/2=5 5*2=10),按照这么算(除2后再乘2)回重新得到一个新的数
#include <cstdio> #include <cstring> #include <iostream> #include <cmath> #include<vector> #include<queue> #include<algorithm> using namespace std; typedef long long LL; const int maxn=1000009; const int INF=0x3f3f3f3f; const int mod=2009; int time[maxn], step[maxn]; void UP(int x, int steps)///统计x的偶数倍 { while(x<=100000) { time[x]++; step[x]+=steps; x*=2; steps++; } } void BFS(int x) { UP(x, 0); int steps = 0; while(x) { steps++; if(x&1 && x>1)///统计x是奇数的情况,并且x!=1 { x/=2; UP(x, steps); } else///统计x是偶数的情况 { x/=2; time[x]++; step[x]+=steps; } } } int main() { int n, num; while(scanf("%d", &n)!=EOF) { memset(time, 0, sizeof(time));///标记这个数被生成了几次 memset(step, 0, sizeof(step));///标记生成这个数的步数 for(int i=1; i<=n; i++) { scanf("%d", &num); BFS(num); } int ans = INF; for(int i=1; i<=100000; i++) { if(time[i] == n)///若这N个数都被标记成了i,取相对应的步数值 ans = min(ans, step[i]); } printf("%d\n", ans); } return 0; } /* 2 1 1 */