题意:
n个数。每次能够选一个数 让其 *=2 或者 /=2
问至少操作多少次使得全部数相等。
思路:
对于每一个数,计算出这个数能够变成哪些数,以及变成那个数的最小步数,用两个数组保存
cnt[i] 表示序列中有cnt个数能够变成i
step[i] 表示能变成i的 那些数 变成i的花费和是多少。
当中。遇到奇数的时候要特殊处理一下:
比方,7 能够通过 /2 然后 *2得到6,也就是说不论什么奇数 i (不包含1)都能够通过2次操作变为 i -1;
代码例如以下:
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; typedef long long ll; const int N = 1e5+10; const int INF = 1e9 + 10; int n; int a[N], cnt[N];//个数 ll step[N];//总步数 void up(int x, int now) { while(x < N) { cnt[x]++; step[x] += now; now++; x <<= 1; } } void go(int u) { up(u, 0); int now = 1; while(u) { if((u>1) && (u&1)) { u >>= 1; up(u, now); } else { u >>= 1; cnt[u]++; step[u] += now; } now++; } } int main() { while(~scanf("%d", &n)) { memset(cnt, 0, sizeof(cnt)); memset(step, 0, sizeof(step)); for(int i = 1; i <= n; i++) { scanf("%d", &a[i]); go(a[i]); } ll ans = step[1]; for(int i = 2; i < N; i++) { if(cnt[i] == n) ans = min(ans, step[i]); } printf("%I64d ", ans); } return 0; }