MIT HAKMEM算法

1.问题来源

牛客刷题

  • 问题描述:
#include <iostream>
using namespace std; unsigned int fib(int n)
{
if(n==0 || n==1)
return 1;
return f(n-1)+f(n-2);
} void count(int n)
{
unsigned int temp= n - ((n>>1)&033333333333) - ((n>>2)&011111111111)
std::cout<< ((temp+(temp>>3))&030707070707) %63 <<std::endl;
} int main()
{
count(f(7));
count(f(9));
return 0;
}

哈哈,看见这个题

这不是 fib数列递归运算后再进行二进制的运算

序号 0 1 2 3 4 5 6 7 8 9 10
fib 1 1 2 3 5 8 13 21 34 55 89

摊手、哈哈 菜 计算不出来!

查找资料 - 这个count函数就是统计bit个数的

f(7)=21=00010101B

f(9)=55= 00110111B

输出: 3,5

2.问题描述:

现在来研究研究这个count函数-统计整数(二进制)中“1”的个数

一些知识点
  • 1.整数性的数值

    \(i=a_{0} * 2^{0} + a_{1} * 2^{1}+a_{2}*2^{2}+...+a_{n}* 2^{n}\)

    所以count “1”的个数

    \(count=a_{0}+a_{1}+a_{2}+...+a_{n}\)

  • 2.对于任何自然数n的N次幂 \(n^{N}\),用n-1 取模得数为1

\[n^{N} \%(n-1)=1
\]

利用归纳法来证明:

假设 \(n^{k-1} \%(n-1)=1\) 成立

证明 \(n^{k} \%(n-1)=1\)

\[n^{k} = (n-1)*n^{k-1} + n^{k-1}
\]

\[(n-1)*n^{k-1} \%(n-1)+ n^{k-1} \%(n-1)=0+1=1
\]

  • 3.一个系数 为\(a_{i}\)以n为底的多项式P(N)

\[P(N)\%(n-1)=\sum a_{i} \%(n-1)
\]

保证$\sum a_{i} $小于余数 $\sum a_{i} < n-1 $

可以推导出

\[P(N)\%(n-1)=\sum a_{i}
\]

32bit的整数,可以取 n=64 n-1=63作为余数来实现count

  • 4.将32位二进制数的每6位作为一个单位,看作以64为底的多项式

    \(I=t_{0}* 64^{0}+ t_{1} * 64^{1} +...+t_{n} * 64^{n}\)

    各个单位中的6位数变为这6位中含有的'1'的个数,再用63取模,就可以得到所求的总的'1'的个数。

  • 5.其中任意一项的6位数ti进行考虑,最简单的方法显然是对每次对1位进行mask然后相加

    (ti>>5)&(000001) + (ti&>>4)(000001) + (ti>>3)&(000001) + (ti>>2)&(000001) + (ti>>1)&(000001) + ti&(000001)

初步实现代码

int bitcount(unsigned int n)
{
unsigned int tmp; tmp = (n &010101010101)
+((n>>1)&010101010101)
+((n>>2)&010101010101)
+((n>>3)&010101010101)
+((n>>4)&010101010101)
+((n>>5)&010101010101); return (tmp%63);
}
  • 6.位数中最多只有6个'1',也就是000110,只需要3位有效位。上面的式子实际上是以1位为单位提取出'1'的个数再相加求和求出6位中'1'的总个数的,所以用的是&(000001)。如果以3位为单位算出'1'的个数再进行相加的话,那么就完全可以先加后MASK。

    tmp = (ti>>2)&(001001) + (ti>>1)&(001001) + ti&(001001)

    (tmp + tmp>>3)&(000111)
int bitcount(unsigned int n)
{
unsigned int tmp; tmp = (n &011111111111)
+((n>>1)&011111111111)
+((n>>2)&011111111111); tmp = (tmp + (tmp>>3)) &030707070707; return (tmp%63);
}
  • 7.最终的优化代码
    unsigned int tmp;

    tmp = n
- ((n >> 1) & 033333333333)
- ((n >> 2) & 011111111111); tmp = (tmp + (tmp >> 3)) & 030707070707 return (tmp%63);
}

参考链接

MIT HAKMEM算法-BitCount算法的更多相关文章

  1. MIT公开课:算法导论 笔记(一)

    课程链接:http://open.163.com/special/opencourse/algorithms.html 第一课:算法分析基础 1.介绍插入排序与归并排序,计算并比较最坏运行时间 2.算 ...

  2. random array & shuffle 洗牌算法 / 随机算法

    random array & shuffle shuffle 洗牌算法 / 随机算法 https://en.wikipedia.org/wiki/Fisher–Yates_shuffle ES ...

  3. GMM算法k-means算法的比较

    1.EM算法 GMM算法是EM算法族的一个具体例子. EM算法解决的问题是:要对数据进行聚类,假定数据服从杂合的几个概率分布,分布的具体参数未知,涉及到的随机变量有两组,其中一组可观测另一组不可观测. ...

  4. 简单易学的机器学习算法——EM算法

    简单易学的机器学习算法——EM算法 一.机器学习中的参数估计问题 在前面的博文中,如“简单易学的机器学习算法——Logistic回归”中,采用了极大似然函数对其模型中的参数进行估计,简单来讲即对于一系 ...

  5. 最短路径算法-Dijkstra算法的应用之单词转换(词梯问题)(转)

    一,问题描述 在英文单词表中,有一些单词非常相似,它们可以通过只变换一个字符而得到另一个单词.比如:hive-->five:wine-->line:line-->nine:nine- ...

  6. 重新想象 Windows 8 Store Apps (31) - 加密解密: 哈希算法, 对称算法

    原文:重新想象 Windows 8 Store Apps (31) - 加密解密: 哈希算法, 对称算法 [源码下载] 重新想象 Windows 8 Store Apps (31) - 加密解密: 哈 ...

  7. Hash散列算法 Time33算法

    hash在开发由频繁使用.今天time33也许最流行的哈希算法. 算法: 对字符串的每一个字符,迭代的乘以33 原型: hash(i) = hash(i-1)*33 + str[i] ; 在使用时.存 ...

  8. 变易算法 - STL算法

    欢迎访问我的新博客:http://www.milkcu.com/blog/ 原文地址:http://www.milkcu.com/blog/archives/mutating-algorithms.h ...

  9. STL非变易算法 - STL算法

    欢迎访问我的新博客:http://www.milkcu.com/blog/ 原文地址:http://www.milkcu.com/blog/archives/1394600460.html 原创:ST ...

随机推荐

  1. activeMQ_helloworld(一)

    一.activeMQ下载,直接在Linux上wget http://mirror.bit.edu.cn/apache//activemq/5.14.5/apache-activemq-5.14.5-b ...

  2. 前端js性能优化的要点

    1 尽量少使用全局查找,比如全局变量,如果要多次使用,可以将全局变量存为局部变量再使用 eg:function(){ var body=document.body; alert(body): body ...

  3. redis过期策略与内存淘汰机制分析

    过期策略: 我们在set key时,可以给一个expire time,就是过期时间 这段过期时间以后,redis对key删除使用:定期删除+惰性删除 定期删除指redis默认在100ms内随机抽取一些 ...

  4. 【JDK】JDK源码分析-AbstractQueuedSynchronizer(2)

    概述 前文「JDK源码分析-AbstractQueuedSynchronizer(1)」初步分析了 AQS,其中提到了 Node 节点的「独占模式」和「共享模式」,其实 AQS 也主要是围绕对这两种模 ...

  5. 记一次python时间格式转换遇到的坑

    需求:拿到指定格式的时间的前一天的时间,如果今天是月初,年初,自动转换,比如:输入时间是:2019-06-27 23:59:59输出时间是:2019-06-26 23:59:59 之前用datetim ...

  6. CEPH RGW多 ZONE的配置

    相关的名称解释 Region :可以理解为区域,是基于地理位置的逻辑划分:如:华南,华北之类,包含多个region的Ceph集群必须指定一个master region,一个region可以包含一个或者 ...

  7. java并发编程(十八)----(线程池)java线程池框架Fork-Join

    还记得我们在初始介绍线程池的时候提到了Executor框架的体系,到现在为止我们只有一个没有介绍,与ThreadPoolExecutor一样继承与AbstractExecutorService的For ...

  8. Thread、ThreadPool、Task、Parallel、Async和Await基本用法、区别以及弊端

    多线程的操作在程序中也是比较常见的,比如开启一个线程执行一些比较耗时的操作(IO操作),而主线程继续执行当前操作,不会造成主线程阻塞.线程又分为前台线程和后台线程,区别是:整个程序必须要运行完前台线程 ...

  9. 想转行大数据,开始学习 Hadoop?

    学习大数据首先要了解大数据的学习路线,首先搞清楚先学什么,再学什么,大的学习框架知道了,剩下的就是一步一个脚印踏踏实实从最基础的开始学起. 这里给大家普及一下学习路线:hadoop生态圈——Strom ...

  10. CodeForces 29D Ant on the Tree

    洛谷题目页面传送门 & CodeForces题目页面传送门 题意见洛谷里的翻译. 这题有\(\bm3\)种解法,但只有一种是正解(这不是废话嘛). 方法\(\bm1\):最近公共祖先LCA(正 ...