月之数
Problem Description
当寒月还在读大一的时候,他在一本武林秘籍中(据后来考证,估计是计算机基础,狂汗-ing),发现了神奇的二进制数。
如果一个正整数m表示成二进制,它的位数为n(不包含前导0),寒月称它为一个n二进制数。所有的n二进制数中,1的总个数被称为n对应的月之数。
例如,3二进制数总共有4个,分别是4(100)、5(101)、6(110)、7(111),他们中1的个数一共是1+2+2+3=8,所以3对应的月之数就是8。
如果一个正整数m表示成二进制,它的位数为n(不包含前导0),寒月称它为一个n二进制数。所有的n二进制数中,1的总个数被称为n对应的月之数。
例如,3二进制数总共有4个,分别是4(100)、5(101)、6(110)、7(111),他们中1的个数一共是1+2+2+3=8,所以3对应的月之数就是8。
Input
给你一个整数T,表示输入数据的组数,接下来有T行,每行包含一个正整数 n(1<=n<=20)。
Output
对于每个n ,在一行内输出n对应的月之数。
Sample Input
3
1
2
3
Sample Output
1
3
8
分析:
1二进制数有1个: 1
2二进制数有2个:10 11
3二进制数有4个:100 101 110 111
4二进制数有8个:1000 1001 1010 1011 1100 1101 1110 1111
可以看到第n二进制数是第(n-1)二进制数 总数目的2倍,他们第一位都是1,所以多出来2n个1。
所有的数字中,一半是在1后边加了第(n-1)二进制数。另一半第一位是1,第二位是0,最后的各个位跟第(n-1)二进制数中最后个各个位都相同,令f[n]表示第n二进制数中1的个数。所以多出来 f[n-1] + (f[n-1] - 2n-1) = 2*f[n-1]-2n-1
所以可以推导出:f[n] = 2n + 2*f[n-1] -2n-1 = 2n-1 + 2*f[n-1]
代码如下:
1 # include<stdio.h> 2 int f[21]={0,1,3}; 3 void init(){ 4 int k=1; 5 for(int i=3; i<21; i++){ 6 k <<= 1; 7 f[i] = k + 2*f[i-1]; 8 } 9 } 10 int main(){ 11 int T; 12 init(); 13 scanf("%d",&T); 14 while(T--){ 15 int n; 16 scanf("%d",&n); 17 printf("%d\n",f[n]); 18 } 19 return 0; 20 }