题意:给定一个数列,每次操作仅仅能将某个数乘以2或者除以2(向下取整)。

求最小的操作次数使得全部的数都变为同样值。

比赛的时候最后没实现。唉。之后才A掉。開始一直在想二分次数,可是半天想不出怎么推断。后来发现事实上每一个数都能变成的数非常少非常少(最多400个不到)。于是想到用数学方法+一点暴力,可惜时间不够了。

也不能全然算是数论题。仅仅是用到了一些数学思想。须要一点预处理,后面的计算中还会用到二分的技巧。

对某个数n,设n = s*2^r(当中s为奇数),则n能变成这样一些数:s*2^k(k = 0,1,2 ...... )以及s能变成的更小的数。s能变成的数有s/2。设s/2 = s'*2^r',则还能变成s'*2^k(k = 0。1,2 ...... )以及s‘能变成的更小的数 ...... 以此类推下去。于是我们能够注意到这样一个情况:假设一个数a能变成数n。那么数a一定能够变成数s。反之。若一个数不能变成数s。那么它一定不能变成数n。进一步,假设两个数a,b都能变成n。那么a和b一定都能变成s。所以,我们能够先求出这个s,即全部的数都能变成s。注意,由于s是奇数,所以每一个数变成s仅仅能是不断除以2(向下取整)的结果。并且,我们至少能够求出一个这种s出来——s
= 1。

这是显然的。所以为了使操作次数更少。我们取s中最大的(当然并不一定最优)。可是显然,全部的数必须都要能够变成这个数,那是肯定的。也就是说,大于这个数的奇数,都无法变到了。

既然这样。那么能够作为最后都变成的候选的数仅仅能是s以及s*2^k(k = 0。1,2 ...... )于是我们枚举k的值,计算每一个数变成s*2^k须要的次数再相加。更新最小值就可以。

求s有点类似于求全部的数的“最大公约数”这种意思。仅仅是这里是求x和y都能变到的最大的奇数而已。也是用递归求:假设x比y的两倍大,那么x/=2,假设y比x的两倍大,那么y/=2。否则x和y同一时候除以2,直到x和y相等。即得到了共同的能变成的最大的奇数。

s攻克了。第二个问题是怎样高速求一个数变成还有一个数所须要的次数。

这里用了一点小技巧,能够直接预处理后以近乎O(1)的复杂度求出。

首先定义一个数组base[i] 、base[i]满足i = base[i]*2^r(事实上basi[i]就是上面所说的s),显然。对于奇数有base[i] = i,对于偶数有base[i] = base[i/2]。

接下来就是计算cal(i, j) = 将 i 变成 j 须要的步数。

能够发现,仅仅要将 i 不断除以2直到base[i] = base[j]为止,此时的 i 和 j 仅仅是差了2的幂的倍数,那么还须要操作这个幂值的次数就可以将 i 变为 j。

而这个幂值就等于log2(max(i,j)/min(i,j))。于是我们仅仅须要求将
i 变为一个base值等于base[j]的数最少要除以多少次2。

当然直接算也能够,就不断除以2直到base值等于base[j]为止。可是外层已经用去了n*log(n)复杂度,于是这里我们再对除以2的次数进行2分。一个数最大10W,最多也就能除以16次2。所以二分的复杂度是log2(16) = 4差点儿就等于O(1)了。能进行二分是由于,若 i 数除以2^k后得到base值比base[j]更小。那么除以大于2^k的值一定更不会得到base[i]了。反之。i 除以2^k后得到的base值若比base[j]大,则它还要继续除以2。

具有单调性,所以能够二分。于是cal(i,j)
= 二分出来的幂值+(int)log2(max(i, j)/min(i, j));

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <algorithm>
  4. #include <cmath>
  5. #include <cstring>
  6. #include <string>
  7. #include <stack>
  8. #include <queue>
  9. #include <vector>
  10. #include <map>
  11. using namespace std;
  12.  
  13. const int MAX = 100005;
  14. const int INF = MAX*20;
  15. int base[MAX];
  16.  
  17. int n, a[MAX];
  18.  
  19. void initial() //预处理base数组
  20. {
  21. for(int i = 1; i <= 100000; i++)
  22. {
  23. if(i%2)
  24. base[i] = i;
  25. else
  26. base[i] = base[i/2];
  27. }
  28. }
  29.  
  30. int getbase(int x, int y) //递归求两个数能同一时候变成的最大的奇数
  31. {
  32. if(x == y)
  33. return x;
  34. if(x >> 1 >= y)
  35. return getbase(x >> 1, y);
  36. if(x << 1 <= y)
  37. return getbase(x, y >> 1);
  38. return getbase(x >> 1, y >> 1);
  39. }
  40.  
  41. int cal(int x, int y) //求将x变成y所须要的步数
  42. {
  43. int l = 0, r = 20, mid;
  44. while(l < r)
  45. {
  46. mid = (l + r) >> 1;
  47. if(base[x >> mid] > base[y])
  48. l = mid + 1;
  49. else
  50. r = mid;
  51. }
  52. x >>= l;
  53. return l + (int)log2(max(x, y)/min(x, y));
  54. }
  55.  
  56. void input()
  57. {
  58. for(int i = 0; i < n; i++)
  59. scanf("%d", &a[i]);
  60. }
  61.  
  62. void solve()
  63. {
  64. int all_base = a[0];
  65. for(int i = 1; i < n; i++)
  66. all_base = getbase(all_base, a[i]); //先求出全部数都能变成的最大奇数all_base
  67. int ans = INF, number = all_base;
  68. while(number <= 100000) //枚举all_base的倍数作为最后变成的数,计算并更新
  69. {
  70. int sum = 0;
  71. for(int i = 0; i < n; i++)
  72. sum += cal(a[i], number);
  73. ans = min(ans, sum);
  74. number <<= 1;
  75. }
  76. printf("%d\n", ans);
  77. }
  78.  
  79. int main()
  80. {
  81. initial();
  82. while(scanf("%d", &n) != EOF)
  83. {
  84. input();
  85. solve();
  86. }
  87. return 0;
  88. }



Codeforces 558C Amr and Chemistry 全都变相等的更多相关文章

  1. 暴力 + 贪心 --- Codeforces 558C : Amr and Chemistry

    C. Amr and Chemistry Problem's Link: http://codeforces.com/problemset/problem/558/C Mean: 给出n个数,让你通过 ...

  2. Codeforces 558C Amr and Chemistry 暴力 - -

    点击打开链接 Amr and Chemistry time limit per test 1 second memory limit per test 256 megabytes input stan ...

  3. CodeForces 558C Amr and Chemistry (位运算,数论,规律,枚举)

    Codeforces 558C 题意:给n个数字,对每一个数字能够进行两种操作:num*2与num/2(向下取整),求:让n个数相等最少须要操作多少次. 分析: 计算每一个数的二进制公共前缀. 枚举法 ...

  4. Codeforces 558C Amr and Chemistry

    题意: n个数.每次能够选一个数 让其 *=2 或者 /=2 问至少操作多少次使得全部数相等. 思路: 对于每一个数,计算出这个数能够变成哪些数,以及变成那个数的最小步数,用两个数组保存 cnt[i] ...

  5. codeforces 558C C. Amr and Chemistry(bfs)

    题目链接: C. Amr and Chemistry time limit per test 1 second memory limit per test 256 megabytes input st ...

  6. 【23.39%】【codeforces 558C】Amr and Chemistry

    time limit per test1 second memory limit per test256 megabytes inputstandard input outputstandard ou ...

  7. Codeforces Round #312 (Div. 2) C. Amr and Chemistry 暴力

    C. Amr and Chemistry Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/558/ ...

  8. Codeforces Round #312 (Div. 2) C.Amr and Chemistry

    Amr loves Chemistry, and specially doing experiments. He is preparing for a new interesting experime ...

  9. C. Amr and Chemistry(Codeforces Round #312 (Div. 2) 二进制+暴力)

    C. Amr and Chemistry time limit per test 1 second memory limit per test 256 megabytes input standard ...

随机推荐

  1. servlet中Cookie的编码问题

    a.什么是Cookie的编码问题?      Cookie只能存放合法的ascii字符,如果是非asicc字符(比如中文),     需要转换成合法的ascii字符的形式.  b.如何处理?     ...

  2. Remember the Word UVALive - 3942 DP_字典树

    每个小单词的长度都是小于等于100的,这是个重要的突破口. Code: #include <cstdio> #include <algorithm> #include < ...

  3. WCF客户端获取服务端异常[自定义异常]

    引言 经过不断的摸索,询问/调试,终于学会了关于WCF客户端与服务端之间异常的处理机制,在此来记录自己的成果,用于记录与分享给需要的伙伴们. 首先感谢[.NET技术群]里群主[轩]的大力帮助,如有需要 ...

  4. java上传文件工具类

    这个是之前整理之前所学时与使用java向邮箱发送邮件一块找到的,一起贴出来供大家参考: import java.awt.image.BufferedImage; import java.io.File ...

  5. webpack 操作

    依赖安装 :  全局安装webpack : sudo npm install webpack -g 本地安装webpack : npm install webpack —save-dev  需要注意的 ...

  6. STM32为什么必须先配置时钟

    首先,任何外设都需要时钟,51单片机,stm32,430等等,因为寄存器是由D触发器组成的,往触发器里面写东西,前提条件是有时钟输入. 51单片机不需要配置时钟,是因为一个时钟开了之后所有的功能都可以 ...

  7. Hive-jdbc获取sessionId

    在HiveStatement中有一个sessHandle: public class HiveStatement implements java.sql.Statement { ... private ...

  8. [Python]Use Flask-Admin with PostgreSQL

    This code recipe gives you an idea of how to use Flask-Admin with postgresql database. from flask im ...

  9. nj11--http

    概念:Node.js提供了http模块.其中封装了一个高效的HTTP服务器和一个建议的HTTP客户端. http.server是一个基于事件的HTTP服务器.内部有C++实现.接口由JavaScrip ...

  10. HTML DOM getAttribute() 方法

    http://www.w3school.com.cn/jsref/met_element_getattribute.asp