Codeforces 558C - Amr and Chemistry (枚举)

来源:互联网 发布:你有毒网络用语 编辑:程序博客网 时间:2024/05/16 01:04

枚举每个数乘二和除二过程中所能到达的所有数,并记录到达时的步数,最后统计在所有数都能到达的数字中步数和最小的数字。

因为只有*2和/2的操作,所以往大往小都是log级的。

注意,如果一个数是奇数,那么它本身一直乘二所能到达的数字,和它除2向下取整再一直乘二所能到达的数字是完全不相同的。因为在二进制下除二后相当于左移把末尾的1弄没了,以后再右移时前缀都不一样了。所以在向下除的过程中每次遇到奇数都要处理一下。


代码:

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;#define LL long longint n;LL c[200005];int b[200005];int a[100005];void up(int n,int k){    if(!n) return ;    while(n<=200000){        b[n]++;        c[n]+=k;        k++;        n<<=1;    }}void solve(int n){    int cur=0;    LL num=n*2;    up(num,1);    num=n;    cur=0;    while(num){        if(num&1){            up(num/2*2,cur+2);        }        b[num]++;        c[num]+=cur;        num>>=1;        cur++;    }}int main(){    scanf("%d",&n);    memset(c,0,sizeof(c));    for(int i=0;i<n;i++){        scanf("%d",&a[i]);        solve(a[i]);    }    LL res=1000000000;    for(int i=0;i<=200000;i++){        if(b[i]==n){            res=min(res,c[i]);        }    }    printf("%lld\n",res);}


0 0