11的n次方十进制表示中1的个数

转自  http://blog.csdn.net/justlinux2010/article/details/8931677

这个题目是群里贴出来的的,只有图片,题目如下:

解题思路:
很明显,这个题目如果直接计算11的n次方的值的话肯定不行,因为n的取值范围是0到1000,在C语言中即使用unsigned long也存储不了这么大的结果。
要解决这个问题,还是要从11这个数本身的特点入手。
我最开始的想法是展开(10+1)^n,然后从这个展开的式子中找到解题方法,但是展开的结果表示这个路子走不通,展开的结果中要计算阶乘,还要计算加法,这样的式子对解题来说没有帮助。
后来,就感觉这个每次乘以11的的结果比较特别,类似杨辉三角似的,所以在纸上开始手动计算11相乘的结果,发现了一个规律:假设现在的值为p(十进制表示),p乘以11的结果就是最低位仍为1,其他位都是p的相邻的两个数逐步相加的结果,当然最高位要做一下特殊处理,拿p的最高位加上进位(有可能两个数字相加的结果大于等于10),如下所示:
1
11
121
1331
14641
161051
1771561
19487171
214358881
2357947691
所以可以这样来解决这个问提:
1)申请两个长度为n(最终的值的十进制位个数不会超过n)的整数数组tmp,curr。tmp存储上个数的十进制表示,curr用来存储现在要计算的数的十进制表示。注意:数组中的每个元素存储的是十进制中的一位
2)循环遍历tmp、curr将各个元素初始化为-1.
3)因为要执行n次11相乘,所以外层循环的次数也是n,而内层循环的次数取决于上次的数的位数。循环计算当前数的值,也就是计算上个数乘以11的值
4)交换tmp、curr的值,然后检查是否执行完毕,否则重复执行第3步操作。
5)循环遍历tmp数组(因为3、4步骤中的循环结束时,tmp中存储的是最终的值),统计数组中1的个数,然后将结果返回
代码实现如下:
[cpp]  view plain copy
  1. #include <stdio.h>  
  2. #include <ctype.h>  
  3. #include <stdlib.h>  
  4.   
  5. void print_array(int *a, int n)  
  6. {  
  7.     int i;  
  8.   
  9.     for (i = n-1; i >= 0; --i) {  
  10.         printf("%d", a[i]);  
  11.     }  
  12.     printf("\n");  
  13. }  
  14.   
  15. int solution(int n)  
  16. {  
  17.     int *curr, *tmp;  
  18.     int tmp_len;  
  19.     int *p;  
  20.     int carry = 0;  
  21.     int i, j;  
  22.     int size = 2*n;  
  23.     int count = 0;  
  24.   
  25.     curr = malloc(sizeof(int) * size);  
  26.     if (!curr) {  
  27.         printf("Out of memory.\n");  
  28.         return -1;  
  29.     }  
  30.   
  31.     tmp = malloc(sizeof(int) * size);  
  32.     if (!tmp) {  
  33.         free(curr);  
  34.         printf("Out of memory.\n");  
  35.         return -1;  
  36.     }  
  37.   
  38.     for (i = 0; i < size; ++i) {  
  39.         curr[i] = -1;  
  40.         tmp[i] = -1;  
  41.     }  
  42.   
  43.     tmp_len = 0;  
  44.     for (i = 0; i < n; ++i) {  
  45.         carry = 0;  
  46.         curr[0] = 1;  
  47.   
  48.         for (j = 1; j < tmp_len; ++j) {  
  49.             curr[j] = tmp[j] + tmp[j - 1] + carry;  
  50.             carry = curr[j] / 10;  
  51.             curr[j] = curr[j] % 10;  
  52.         }  
  53.   
  54.         if (i > 0) {  
  55.             curr[j] = tmp[j - 1] + carry;  
  56.             if (curr[j] >= 10) {  
  57.                 curr[j] = curr[j] % 10;  
  58.                 curr[++j] = 1;  
  59.             }  
  60.             tmp_len = ++j;  
  61.         } else {  
  62.             tmp_len = 1;  
  63.         }  
  64.           
  65.         p = tmp;  
  66.         tmp = curr;  
  67.         curr = p;  
  68.     }  
  69.   
  70.     for (i = 0; i < size; ++i) {  
  71.         printf("%d", tmp[i]);  
  72.         if (tmp[i] == 1) {  
  73.             ++count;  
  74.         }  
  75.     }  
  76.     printf("\ncount = %d.\n", count);  
  77.   
  78.     free(tmp);  
  79.     free(curr);  
  80.     return 0;  
  81. }  
  82.   
  83. int main(void)  
  84. {  
  85.     solution(1000);  
  86.     return 0;  
  87. }  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 要将一个二进制数转换为十进制表示法,需要将每位上的二进制数与其对应的权重相乘,然后将所有结果相加。 假设输入的二进制数为c,长度为n位。 首先,我们从最右边的位开始,即最低位是1的位。该位的权重为1,因为2^0=1。如果这一位是0,则对结果没有影响;如果这一位是1,则将结果加上1。 接下来,我们继续处理下一个位,即第二低位。将这一位的权重设为2,因为2^1=2。如果这一位是0,则对结果没有影响;如果这一位是1,则将结果加上2。 以此类推,每次处理一位时,将该位的权重设为2的指数幂(2的n-1次方),然后根据该位的数值(0或1)将结果相应地加上(如果该位是0,则不加)。 最后,当处理完所有位时,得到的结果就是将输入的二进制数转换为十进制表示法的结果。 综上所述,要将一个二进制数转换为十进制表示法,需要按照上述方法逐位处理,并将每位的二进制数与对应权重相乘,最后将所有结果相加。完成这些步骤后,输出的结果就是输入的二进制数的十进制表示法。 ### 回答2: 要将一个二进制数转换成十进制表示法,需要使用权重的概念。 二进制数是以2为基数的数制,每一位的权重都是2的n次方,其n表示该位在二进制数的位置。例如,二进制数1010可以表示为(1 × 2³) + (0 × 2²) + (1 × 2¹) + (0 × 2⁰),其,1代表该位上有1个1,0代表该位上没有1。 具体步骤如下: 1. 从最右边的位开始,将每一位上的数字与对应的权重相乘。 2. 将所有的乘积相加,得到最终的十进制表示法。 举个例子,假设输入的二进制数为1010: 1. 从最右边的位开始,第一位为0,权重为2⁰,乘积为0。 2. 第二位为1,权重为2¹,乘积为2。 3. 第三位为0,权重为2²,乘积为0。 4. 第四位为1,权重为2³,乘积为8。 5. 将所有乘积相加,0 + 2 + 0 + 8 = 10。 6. 因此,该二进制数转换成十进制表示法为10。 综上所述,将一个二进制数转换为十进制表示法的方法是:从最右边的位开始,将每一位上的数字与对应的权重相乘,然后将所有的乘积相加。 ### 回答3: 首先,需要明确二进制数是由0和1组成的数字系统。而十进制数是我们通常使用的数字系统,由0到9的十个基本数字组成。 要将一个二进制数转换为十进制数,我们需要按权相加的原理进行计算。具体步骤如下: 1. 从二进制数的最右边(个位)开始计算。将该位上的数字乘以2的0次方(即1),得到该位的十进制值。 2. 继续向左计算,将每个位上的数字乘以2的n次方,n为该位与右边第一位之间的位数值。依次计算每个位的十进制值。 3. 将所得到的十进制值相加,得到最终的结果。 举个例子,假设输入的二进制数为101010,按照以上步骤进行计算: 1. 个位上的数字是0,乘以2的0次方得到0。 2. 十位上的数字是1,乘以2的1次方得到2。 3. 百位上的数字是0,乘以2的2次方得到0。 4. 千位上的数字是1,乘以2的3次方得到8。 5. 万位上的数字是0,乘以2的4次方得到0。 6. 十万位上的数字是1,乘以2的5次方得到32。 最后将所有的十进制值相加,即0 + 2 + 0 + 8 + 0 + 32 = 42。所以,给定的二进制数101010的十进制表示为42。 但需要注意的是,以上步骤为手动计算的方法。在计算机,可以直接使用函数或转换操作符进行二进制到十进制的转换。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值