Amr and Chemistry (枚举&二进制)
- 时间 : 2019年03月25日
- 作者 : 数字_ID
题意
给你一些数,你只能 ∗ 2 * 2 ∗2 或者 ÷ 2 \div2 ÷2(向下取整),让你用最小的次数实现让每个数都相等,并输出最小次数
题解
- 首先把所有数全部左移到最高
- 通过同或得到公共的01串
- 枚举这个01串后面0的个数的所有可能,暴力地去计算所有代价
代码
#include <stdio.h>
#include <map>
#include <utility>
#include <functional>
#include <algorithm>
#include <iostream>
#include <queue>
#include <vector>
#include <string>
#include <string.h>
#include <stack>
#include <set>
#include <math.h>
#define lowbit(x) (x & (-x) )
#define ul unsigned int
using namespace std;
ul arr[100020];
ul num[100020];
ul brr[100020];
ul get_cnt(ul now)
{
ul cnt = 0;
while(now){
cnt ++;
now = now & (now - 1);
}
return cnt;
}
int main()
{
ul n;
cin >> n;
for(ul i = 0;i<n;i++)cin >> arr[i];
for(ul i = 0;i<n;i++){
brr[i] = arr[i] << ((31-(ul)log2(arr[i])));
}
for(ul i = 0;i<n;i++)num[i] = get_cnt(arr[i]);
ul temp = (ul)((1ll << 32) - 1ll);
for(ul i = 1;i<n;i++){
ul res = ~(brr[0] ^ brr[i]);
temp = temp & res;
}
temp = brr[0] & temp;
ul f_cnt = get_cnt(temp);
ul st = log2(lowbit(temp));
//cout << st << endl;
ul mn = 0x3f3f3f3f;
for(ul i = 0;i <= st;i++)
{
ul now = temp >> i;
//cout << now << endl;
ul cst = 0;
for(ul j = 0;j<n;j++){
ul nn = arr[j];
if((ul)log2(now) > (ul)log2(arr[j])){
while(f_cnt < get_cnt(nn)){
//cout << "fuck" << endl;
cst ++;
nn >>= 1;
}
while(now > nn){
cst ++;
nn <<= 1;
}
}else{
while(f_cnt < get_cnt(nn)){
cst ++;
nn >>= 1;
}
while(nn < now){
cst++;
nn <<= 1;
}
while(nn > now){
cst ++;
nn >>= 1;
}
}
}
mn = min(mn , cst);
}
cout << mn << endl;
return 0;
}