• 剑指OFFER之从1到n中出现1的次数(九度OJ1373)


    题目描述:

    亲们!!我们的外国友人YZ这几天总是睡不好,初中奥数里有一个题目一直困扰着他,特此他向JOBDU发来求助信,希望亲们能帮帮他。问题是:求出1~13的整数中1出现的次数,并算出100~1300的整数中1出现的次数?为此他特别数了一下1~13中包含1的数字有1、10、11、12、13因此共出现6次,但是对于后面问题他就没辙了。ACMer希望你们帮帮他,并把问题更加普遍化,可以很快的求出任意非负整数区间中1出现的次数。

     

    输入:

    输入有多组数据,每组测试数据为一行。

    每一行有两个整数a,b(0<=a,b<=1,000,000,000)。

     

    输出:

    对应每个测试案例,输出a和b之间1出现的次数。

     

    样例输入:
    0 5
    1 13
    21 55
    31 99
    样例输出:
    1
    6
    4
    7

    解题思路:

      这道题目要注意几个问题:

      第一个,比如10 到15 出现几个1?是7个...数字10 12 13 14 15各出现一次,11出现两次,因此是7次

      第二个,输入的两个数,第一个数,可能比第二个大。因此如果第一个数大于第二个数要进行一次调整。

        if(n>m)
                swap(&n,&m);

      第三个,就是这道题的主要思想。

      主要思想,通过递归来求解。我们分别求出两个数含有1的个数,但是要注意,对小的的数求解时,要减1.因为如果是10到15,0到10应该含有2个1,而0到15含有8个1,如果直接相减,10的那个1就被减掉了。因此要减1求解。

         char numN[MAXSIZE];
            char numM[MAXSIZE];
            sprintf(numN,"%d",n-1);
            sprintf(numM,"%d",m);
            numberOfN = getNumber(numN);
            numberOfM = getNumber(numM);
            printf("%d
    ",numberOfM-numberOfN);

      算法主要思想,首先我们看最高位。把数分解,abcde就分解成bcde+1到abcde 与 1到bcde两段。比如,34567分解成4568到34567,1到4567.这样求解第一段,只需要考虑第一位,和后面几位的普通情况就行了。然后递归求第二段。

      如果最高位是大于1的数。那么就分包含1的情况,和1以外的情况。

      对于最高位是1的,后面无论是什么都满足情况。因此,如果高位刚好等于1,那么满足的情况更应该是后面的数字之和。举个例子,

      12345,最高位为1时,满足的情况为2345种(不考虑后面的)。

        numF = 0;
        if(firstNum > 1)
            numF = power(length-1);
        else if(firstNum == 1)
            numF = atoi(num+1)+1;        

      而22345,最高位大于1时,满足的情况为10000-19999,即10000种。

      接下来,分析下最高位不是1时候,应该就是后面的个个位数为1其他位随机的数目。即,first*(lengt-1)*power(length-2),即在本例中为2*4*1000种,即11000,11001,11002,11003...21000,21002,21003,21004...即每一位为1*其他几位的随机数。此处就是4*1000.

    int getNumber(const char *num){
        int firstNum = *num-'0';
        int length = strlen(num);
        int numF,numOther,numL;
        if(!num || *num < '0' || *num > '9' || *num == '')
            return 0;
        if(length == 1 && firstNum == 0)
            return 0;
        if(length == 1 && firstNum > 0)
            return 1;
    
        numF = 0;
        if(firstNum > 1)
            numF = power(length-1);
        else if(firstNum == 1)
            numF = atoi(num+1)+1;
    
        numOther = firstNum*(length-1)*power(length-2);
    
        numL = getNumber(num+1);
    
        return numF + numOther + numL;
    }

    全部代码:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #define MAXSIZE 32
    int getNumber(const char *num);
    int power(int length);
    void swap(int *a,int *b);
    int main(){
        int n,m,numberOfN,numberOfM;
        while(scanf("%d %d",&n,&m)!=EOF ){
            if(n>m)
                swap(&n,&m);
            char numN[MAXSIZE];
            char numM[MAXSIZE];
            sprintf(numN,"%d",n-1);
            sprintf(numM,"%d",m);
            numberOfN = getNumber(numN);
            numberOfM = getNumber(numM);
            printf("%d
    ",numberOfM-numberOfN);
            //printf("%d
    ",n%10 == 1?(numberOfM - numberOfN+1):(numberOfM-numberOfN));
        }
        return 0;
    }
    int getNumber(const char *num){
        int firstNum = *num-'0';
        int length = strlen(num);
        int numF,numOther,numL;
        if(!num || *num < '0' || *num > '9' || *num == '')
            return 0;
        if(length == 1 && firstNum == 0)
            return 0;
        if(length == 1 && firstNum > 0)
            return 1;
     
        numF = 0;
        if(firstNum > 1)
            numF = power(length-1);
        else if(firstNum == 1)
            numF = atoi(num+1)+1;
     
        numOther = firstNum*(length-1)*power(length-2);
     
        numL = getNumber(num+1);
     
        return numF + numOther + numL;
    }
    int power(int length){
        int i;
        int result = 1;
        for(i=0;i<length;i++){
            result *= 10;
        }
        return result;
    }
    void swap(int *a,int *b){
        int tmp = *b;
        *b = *a;
        *a = tmp;
    }
    /**************************************************************
        Problem: 1373
        User: xhalo
        Language: C
        Result: Accepted
        Time:10 ms
        Memory:916 kb
    ****************************************************************/
  • 相关阅读:
    [NOI2017]游戏
    [USACO09MAR]Cleaning Up
    [POI2010]Blocks
    [JSOI2011]分特产
    [POI2001]Peaceful Commission
    BZOJ4152 [AMPPZ2014]The Captain
    Luogu P3783 [SDOI2017]天才黑客
    Luogu P3645 [APIO2015]雅加达的摩天楼
    Luogu P1613 跑路
    AGC009E Eternal Average
  • 原文地址:https://www.cnblogs.com/xing901022/p/3792559.html
Copyright © 2020-2023  润新知