标签:codeforces
题意:
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\n", ans); } return 0; }
版权声明:本文为博主原创文章,未经博主允许不得转载。
Codeforces 558C Amr and Chemistry
标签:codeforces
原文地址:http://blog.csdn.net/doris1104/article/details/46911585