编程之美--高效率算出1的数目之扩展问题
2012-12-26 11:19
246 查看
问题:给定一个十进制数N,写下从1开始,到N的所有二进制数,然后数一下其中出现的所有“1”的个数。
问题分析:
首先我们看2,、4、8、16四个数,2的二进制数总共有2个1,4的有5个,8的有13个,16有33个。而且他们都有一定的规律。比如16是2的4次方,二进制数是10000,在最右边1的个数和倒数第二、第三、第四都是8(即4个8),最高位是1;8是2的3次方,二进制数是01000,在最右边1的个数和倒数第二、第三都是4(3个4),倒数第四个是1;以此类推4和2,那么我们可以看出符合这样的公式:
0~2^n的所有二进制数1的总和sum=2^(n-1)*n+1 其中2^n表示2的n次方
现在我们观察0~24的数的二进制的最右边位的1的个数总和,0,1,1,2,2,3,3,4,4,5,5,6,6...,可以得出这样的公式:
0~n的所有二进制数最右边位的1的个数总和sum:当n%2=0时,sum=n/2; 否则sum=n/2+1。
观察倒数第二位1的总和。0~1是0,其他的都是一个常数带上三个相同的常数;比如1,2,2,2,;3,4,4,4;5,6,6,6.... 那么设他们的规律是1+3为一组。
我们设sequenceLength=1,repeatLength=3;
这样子我们可以计算出18的二进制数的倒数第二位的1的总和为:看上面表格知道从0开始,那么18就是第19位,看倒数第二1的个数这一列前面是两个0,推出(18+1-2)/(1+3)取整为4,就是说有4组,每组的值其实是两个,那么sum=4*2=8,而(18+1-2)%(1+3)=1;所以sum=4*2+1=9;
观察倒数第三位1的总和。0~3是0,其他的都是三个常数带上五个相同的常数;比如1,2,3,4,4,4,4,4;5,6,7,8,8,8,8,8;9,10,11,12,12,12,12,12.... 那么设他们的规律是3+5为一组。
这样子我们可以计算出18的二进制数的倒数第三位的1的总和为:看上面表格知道从0开始,那么18就是第19位,看倒数第三1的个数这一列前面是四个0,推出(18+1-4)/(3+5)取整为1,就是说有1组,每组的值其实是4个,那么sum=1*4=4,而(18+1-4)%(3+5)=7;就是说18这个数为一组还多七个,由3+5为一组可知,多出来的七个的前三个的值是连续的,后面四个是一样的。那么这多出来的七个数其实就是3+1个值,推出sum=1*4+(3+1)=8。
观察倒数第四位1的总和。0~7是0,其他的都是三个常数带上五个相同的常数;比如1,2,3,4,5,6,7,8,8,8,8,8,8,8,8,8;.... 那么设他们的规律是7+9为一组
这样子我们可以计算出18的二进制数的倒数第四位的1的总和为:看上面表格知道从0开始,那么18就是第19位,看倒数第四1的个数这一列前面是八个0,推出(18+1-8)/(7+9)取整为0,就是说有0组,每组的值其实是8个,那么sum=0*8=0,而(18+1-8)%(7+9)=11;就是说18这个数为零组还多十一个,由7+9为一组可知,多出来的十一个的前七个的值是连续的,后面九个是一样的。那么这多出来的十一个数其实就是7+1个值,推出sum=0*8+(7+1)=8。
倒数第二位、倒数第三位。。。倒数第N位的组的规律。
1+3;3+5;7+9 可知(1+2^1)+(3+2^1)=3+5; (3+2^2)+(5+2^2)=7+9......
和面组是前面组的2的幂次方。倒数第二位是2的一次方,倒数第三位是2的两次方...以此类推。
代码分析:
View Code
问题分析:
十进制 | 二进制 | 最右边1的个数总和 | 倒数第二1的个数总和 | 倒数第三1的个数总和 | 倒数第四1的个数总和 | 倒数第五1的个数总和 | 十进制 | 二进制 | 最右边1的个数总和 | 倒数第二1的个数总和 | 倒数第三1的个数总和 | 倒数第四1的个数总和 | 倒数第五1的个数总和 |
0 | 00000 | 0 | 0 | 0 | 0 | 0 | 13 | 01101 | 7 | 6 | 6 | 6 | 0 |
1 | 00001 | 1 | 0 | 0 | 0 | 0 | 14 | 01110 | 7 | 7 | 7 | 7 | 0 |
2 | 00010 | 1 | 1 | 0 | 0 | 0 | 15 | 01111 | 8 | 8 | 8 | 8 | 0 |
3 | 00011 | 2 | 2 | 0 | 0 | 0 | 16 | 10000 | 8 | 8 | 8 | 8 | 1 |
4 | 00100 | 2 | 2 | 1 | 0 | 0 | 17 | 10001 | 9 | 8 | 8 | 8 | 2 |
5 | 00101 | 3 | 2 | 2 | 0 | 0 | 18 | 10010 | 9 | 9 | 8 | 8 | 3 |
6 | 00110 | 3 | 3 | 3 | 0 | 0 | 19 | 10011 | 10 | 10 | 8 | 8 | 4 |
7 | 00111 | 4 | 4 | 4 | 0 | 0 | 20 | 10100 | 10 | 10 | 9 | 8 | 5 |
8 | 01000 | 4 | 4 | 4 | 1 | 0 | 21 | 10101 | 11 | 10 | 10 | 8 | 6 |
9 | 01001 | 5 | 4 | 4 | 2 | 0 | 22 | 10110 | 11 | 11 | 11 | 8 | 7 |
10 | 01010 | 5 | 5 | 4 | 3 | 0 | 23 | 10111 | 12 | 12 | 12 | 8 | 8 |
11 | 01011 | 6 | 6 | 4 | 4 | 0 | 24 | 11000 | 12 | 12 | 12 | 9 | 9 |
12 | 01100 | 6 | 6 | 5 | 5 | 0 | 25 | 11001 | 13 | 12 | 12 | 10 | 10 |
0~2^n的所有二进制数1的总和sum=2^(n-1)*n+1 其中2^n表示2的n次方
现在我们观察0~24的数的二进制的最右边位的1的个数总和,0,1,1,2,2,3,3,4,4,5,5,6,6...,可以得出这样的公式:
0~n的所有二进制数最右边位的1的个数总和sum:当n%2=0时,sum=n/2; 否则sum=n/2+1。
观察倒数第二位1的总和。0~1是0,其他的都是一个常数带上三个相同的常数;比如1,2,2,2,;3,4,4,4;5,6,6,6.... 那么设他们的规律是1+3为一组。
我们设sequenceLength=1,repeatLength=3;
这样子我们可以计算出18的二进制数的倒数第二位的1的总和为:看上面表格知道从0开始,那么18就是第19位,看倒数第二1的个数这一列前面是两个0,推出(18+1-2)/(1+3)取整为4,就是说有4组,每组的值其实是两个,那么sum=4*2=8,而(18+1-2)%(1+3)=1;所以sum=4*2+1=9;
观察倒数第三位1的总和。0~3是0,其他的都是三个常数带上五个相同的常数;比如1,2,3,4,4,4,4,4;5,6,7,8,8,8,8,8;9,10,11,12,12,12,12,12.... 那么设他们的规律是3+5为一组。
这样子我们可以计算出18的二进制数的倒数第三位的1的总和为:看上面表格知道从0开始,那么18就是第19位,看倒数第三1的个数这一列前面是四个0,推出(18+1-4)/(3+5)取整为1,就是说有1组,每组的值其实是4个,那么sum=1*4=4,而(18+1-4)%(3+5)=7;就是说18这个数为一组还多七个,由3+5为一组可知,多出来的七个的前三个的值是连续的,后面四个是一样的。那么这多出来的七个数其实就是3+1个值,推出sum=1*4+(3+1)=8。
观察倒数第四位1的总和。0~7是0,其他的都是三个常数带上五个相同的常数;比如1,2,3,4,5,6,7,8,8,8,8,8,8,8,8,8;.... 那么设他们的规律是7+9为一组
这样子我们可以计算出18的二进制数的倒数第四位的1的总和为:看上面表格知道从0开始,那么18就是第19位,看倒数第四1的个数这一列前面是八个0,推出(18+1-8)/(7+9)取整为0,就是说有0组,每组的值其实是8个,那么sum=0*8=0,而(18+1-8)%(7+9)=11;就是说18这个数为零组还多十一个,由7+9为一组可知,多出来的十一个的前七个的值是连续的,后面九个是一样的。那么这多出来的十一个数其实就是7+1个值,推出sum=0*8+(7+1)=8。
倒数第二位、倒数第三位。。。倒数第N位的组的规律。
1+3;3+5;7+9 可知(1+2^1)+(3+2^1)=3+5; (3+2^2)+(5+2^2)=7+9......
和面组是前面组的2的幂次方。倒数第二位是2的一次方,倒数第三位是2的两次方...以此类推。
代码分析:
View Code
class Program { static void Main(string[] args) { NumberOfOne numberOfOne = new NumberOfOne(); while (true) { int number = int.Parse(Console.ReadLine()); numberOfOne.BinaryCount(number); Console.WriteLine("0~{0}的所有二进制数的1的总和为:{1}", number, numberOfOne.Sum); if (number == 444) { break; } } Console.ReadLine(); } }
相关文章推荐
- 编程之美--2.4 1的数目之扩展问题
- 编程之美 2.4 “1”的数目及扩展问题
- 关于php扩展编程如何返回数组的问题
- 编程之美 - 满足条件的两个数字及扩展问题
- 编程之美---快速寻找满足条件的两个数---扩展问题
- 编程之美--求数组的子数组之和的最大值--扩展问题
- 编程之美 4.2 瓷砖覆盖地板 扩展问题
- 编程之美 寻找发帖水王 扩展问题
- [zz]编程之美-重建二叉树扩展问题1 2
- 编程之美 扩展问题 之 如何处理二维空间的覆盖问题。
- 编程之美 3.9 重建二叉树 扩展问题
- 1的数目_扩展问题
- 编程之美3.1字符串移位包含的问题的扩展问题
- 编程之美----三角形测试用例扩展问题2
- 编程之美 - 一排石头游戏及扩展问题
- 编程之美 2.3 寻找发帖水王扩展问题
- 编程之美---发帖“水王”扩展问题
- 编程之美3.11扩展问题 简单并带有错误的环形单链表检测代码
- 最近碰到个问题,关于php扩展编程如何返回数组的问题
- 编程之美 - 寻找灌水王及扩展问题