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


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

    解题思路:
    很明显,这个题目如果直接计算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的个数,然后将结果返回
     
    代码实现如下:
    #include <stdio.h>
    #include <ctype.h>
    #include <stdlib.h>
    
    void print_array(int *a, int n)
    {
        int i;
    
        for (i = n-1; i >= 0; --i) {
            printf("%d", a[i]);
        }
        printf("\n");
    }
    
    int solution(int n)
    {
        int *curr, *tmp;
        int tmp_len;
        int *p;
        int carry = 0;
        int i, j;
        int size = n;
        int count = 0;
    
        curr = malloc(sizeof(int) * size);
        if (!curr) {
            printf("Out of memory.\n");
            return -1;
        }
    
        tmp = malloc(sizeof(int) * size);
        if (!tmp) {
            free(curr);
            printf("Out of memory.\n");
            return -1;
        }
    
        for (i = 0; i < size; ++i) {
            curr[i] = -1;
            tmp[i] = -1;
        }
    
        tmp_len = 0;
        for (i = 0; i < n; ++i) {
            carry = 0;
            curr[0] = 1;
    
            for (j = 1; j < tmp_len; ++j) {
                curr[j] = tmp[j] + tmp[j - 1] + carry;
                carry = curr[j] / 10;
                curr[j] = curr[j] % 10;
            }
    
            if (i > 0) {
                curr[j] = tmp[j - 1] + carry;
                if (curr[j] >= 10) {
                    curr[j] = curr[j] % 10;
                    curr[++j] = 1;
                }
                tmp_len = ++j;
            } else {
                tmp_len = 1;
            }
            
            p = tmp;
            tmp = curr;
            curr = p;
        }
    
        for (i = 0; i < size; ++i) {
            printf("%d", tmp[i]);
            if (tmp[i] == 1) {
                ++count;
            }
        }
        printf("\ncount = %d.\n", count);
    
        free(tmp);
        free(curr);
        return 0;
    }
    
    int main(void)
    {
        solution(1000);
        return 0;
    }
    


    如果有什么错误,请帮忙指针,多谢!以免误人子弟.....
  • 相关阅读:
    AGC044D Guess the Password
    CF1290E Cartesian Tree
    loj2537. 「PKUWC2018」Minimax
    loj3166. 「CEOI2019」魔法树
    CF702F T-Shirts
    CF1260F Colored Tree
    CF1340F Nastya and CBS
    CF1017G The Tree
    CF150E Freezing with Style
    前端开发 -- HTML
  • 原文地址:https://www.cnblogs.com/javawebsoa/p/3080499.html
Copyright © 2020-2023  润新知