博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
codeforces #312C 558C C. Amr and Chemistry(位运算)
阅读量:3711 次
发布时间:2019-05-21

本文共 1877 字,大约阅读时间需要 6 分钟。

题目链接:

题目大意:

给出一些数,他们能做的操作是左移和右移,问最少做多少次操作能把他们都变成相同的数

题目分析:

首先要知道,左移的话的只是在二进制数末尾填0,而右移则要根据末尾是0还是1,如果是1的话,那么再左移的话会得到完全不同的结果,如果是0的话,那么再左移只是还原没有意义。所以做法就是对初始的数左移得到的数全是最短距离,然后右移得到的数去全是最短操作数,然后每次右移吞掉1的时候,再左移得到所有可能得到的结果,用dp[i]记录所有数到达i的最小操作数的总数,因为每次得到这个数时的操作数一定是最小的(没有做多余的操作),然后另开一个数组记录对于i是不是所有数都能到达,然后最后比较能够全部到达的数的总操作数最小的那个就是最终结果

代码如下:

#include 
#include
#include
#include
#define MAX 100007using namespace std;int n;int a;int dp[MAX];int vis[MAX];int main ( ){ while ( ~scanf ( "%d" , &n ) ) { memset ( vis , 0 , sizeof ( vis )); memset ( dp , 0 , sizeof (dp)); int judge = n; while ( n-- ) { scanf ( "%d" , &a ); int num = 0; int temp = a; while ( temp <= 1e5 ) { vis[temp]++; dp[temp] += num; temp <<= 1; num++; } num = 0; while ( a ) { if ( a&1 && a != 1 ) { int temp = (a>>1)<<1; int sum = num+2; while ( temp <= 1e5 ) { vis[temp]++; dp[temp] += sum; temp<<=1; sum++; } } num++; dp[a>>=1] += num; vis[a]++; } } /*cout << "dp : " << endl; for ( int i = 1 ; i <= 10 ; i++ ) printf ( "%d " , dp[i] ); puts("");*/ /*cout << "vis : " << endl; for ( int i = 1 ; i <= 10 ; i++ ) printf ( "%d " , vis[i] ); puts("");*/ int ans = 1e9; for ( int i = 0 ; i <= 1e5 ;i++ ) if (vis[i] == judge ) ans = min ( ans , dp[i] ); printf ( "%d\n" , ans ); }}

转载地址:http://uvvjn.baihongyu.com/

你可能感兴趣的文章
python颜值分析
查看>>
python表白代码,照片隐藏表白话语!
查看>>
python报错cannot import name ‘BeautifulSoup‘ from ‘bs4‘
查看>>
记录博客第一次上热门
查看>>
python爬虫实战(2)——爬取知乎热榜内容
查看>>
python爬虫实战(1)——爬取知乎热门回答图片
查看>>
用户线程和守护线程
查看>>
线程组的使用
查看>>
synchronized关键字
查看>>
线程安全的实现方法
查看>>
ReentrantLock锁详解
查看>>
多线程中Condition的用法
查看>>
LockSupport实现等待唤醒机制
查看>>
Semaphore信号量真的晦涩难懂?
查看>>
CyclicBarrier的使用
查看>>
线程池深入浅出也就这一篇了!
查看>>
Executors一篇就够
查看>>
ScheduledThreadPoolExecutor类的使用
查看>>
JUC中的原子类操作
查看>>
如何挑选笔记本电脑?
查看>>