第十二节 机试题目之十进制1~N的所有整数中出现“1”的个数

来源:互联网 发布:cmd怎么测试端口 编辑:程序博客网 时间:2024/05/18 01:49
第十二节  机试题目之十进制1~N的所有整数中出现“1”的个数

给定一个十进制数N,写下从1开始到N的所有整数,然后数一下其中出现的所有“1”的个数,比如:
1)   N = 2 ,写下1、2,这样只出现1个“1”;
2)   N= 12 ,我们会写下1、2、3、4、5、6、7、8、9、10、11、12,这样1的个数为5。
问题是:写一个函数f(N),返回1~N之间出现“1”的个数,比如:f(12) = 5。
这个题目带有几分找规律性质。本题解法可能较多,这里提供两种。
方法一:
// text.cpp : 定义控制台应用程序的入口点。
#include "stdafx.h"
/****************************************************************
** Function name      oneNumber
** Descriptions       计算1的个数
** input parameters  uliNumber:输入的数据,即为要计算1的个数的数据
** output parameters void
** Returned value     uliCount1的个数
****************************************************************/
unsigned long int oneNumber ( unsigned long int uliNumber )
{
    /*  uliNumber传进来的值赋给uliTally */
    unsigned long int uliTally           = uliNumber ;
    /*  记录1的个数 */
    unsigned long int uliCount           = 0 ;   
    /*  提取位的权值 */
    unsigned long int uliFlag            = 1 ;
    /*  提取位 */
    unsigned int      uiFlag              = 0 ;
    /*  提取位的幂次方 */
    unsigned int      uiLog               = 0 ;
    /*
     *对数据逐位取提取位
     */
while (  ( uliTally / uliFlag )  != 0 )
{
       /* 从左开始计算,依次取出uiFlag*10^n */
       uiFlag   = ( uliTally / uliFlag ) % 10  ;
       /* 如果是 1 * 10^n ,则按1*10^n公式进行计算 */
       if ( 1 == uiFlag )
{
           uliCount += uiLog * ((unsigned long int)( uliFlag / 10)) + 1 ;
           /* 加上10^n后面数据 */
           uliCount += ( uliNumber % uliFlag  ) ;
       }  
/*
*如果是 uiFlag * 10^n ,则按uiFlag*10^n公式进行计算
*/
else
{
           /*( uliFlag ) * ( 1&&uiFlag )是为了uliFlag0,则是加0 */
           uliCount += ( uliFlag ) * ( 1&&uiFlag ) +
            uiFlag * uiLog * ( (unsigned long int)( uliFlag / 10) ) ;
       }
       /* 依次向左取 */
       uliFlag *= 10 ;
       /* uiLog = log10(uliFlag) */
       uiLog   += 1 ;
    }
    /* 返回1的个数 */
    return uliCount ;
}
/****************************************************************
** Function name      main
** Descriptions       输入输出
** input parameters   argc  argv[]
** output parameters  void
** Returned value     0
****************************************************************/
int main(int argc, char* argv[])
{
    unsigned long int iNumber = 0 ;
    unsigned long int uliCountNumber = 0 ;
    printf("请输入iNumber:  ") ;
    scanf("%ld" , &iNumber) ;
    uliCountNumber =  oneNumber(iNumber) ;
    printf( "1~%d1的个数为: %d\n" , iNumber , uliCountNumber ) ;
    return 0;
}
函数头文件这里使用的是英语,但是格式是不变的。
编译结果:
请输入iNumber:  100
1~1001的个数为: 21
请按任意键继续. . .
方法二:
// text.cpp : 定义控制台应用程序的入口点。
#include "stdafx.h"
/****************************************************************
** Function name      oneNumber
** Descriptions       计算1的个数
** input parameters   uliNumber:输入的数据,即为要计算1的个数的数据
** output parameters  void
** Returned value     uliCount1的个数
****************************************************************/
unsigned long int oneNumber ( unsigned long int uliNumber )
{
    /*
    **  记录1的个数
    */
    unsigned long int uliCount           = 0 ;   
    /*
    **  提取位左边的数
    */
    unsigned long int uliLeft            = 0 ;
    /*
    **  提取位右边的数
    */
    unsigned long int uliRight           = 0 ;
    /*
    **  提取位,此位对1进行计数
    */
    unsigned long int uliFlag            = 0 ;
    /*
    **  提取位的权值
    */
    unsigned int      uiFlag             = 1 ;
    /*
    ** 对数据逐位取提取位
    */
    while ( (uliNumber / uiFlag)!=0 )
{
       /*
       ** 提取位右边的数
       */
       uliRight = uliNumber % uiFlag          ;
       /*
       ** 提取位
       */
       uliFlag  = ( uliNumber / uiFlag ) % 10 ;
       /*
       ** 提取位左边的数
       */
       uliLeft  = ( uliNumber / uiFlag ) / 10 ;
       /*
       ** 判断提取位,分成01和大于等于2这三种情况
       */
       switch ( uliFlag )
{
        
       /*
       ** 如果提取位为0,那么1的个数等于提取位左边数乘以取提取位的数据
       */
       case 0  :
{
           uliCount += uliLeft * uiFlag ;
       } break ;
       /*
       ** 如果提取位为1,那么1的个数等于提取位左边数乘以取提取位的数据
       ** 再加上(0到提取位右边数)+1
       */
       case 1  :
{
           uliCount += uliLeft * uiFlag + uliRight + 1 ;
       } break;
       /*
       ** 如果提取位大于1,那么1的个数等于(提取位左边数+1)乘以
       ** 取提取位的数据
       */
       default :
{
           uliCount += ( uliLeft + 1 ) * uiFlag ;
       } break;
       }
       /*
       ** 提取位向左移动一位
       */
       uiFlag *= 10 ;
    }
    /*
    **  返回1的个数
    */
    return uliCount ;
}
/****************************************************************
** Function name      main
** Descriptions       输入输出
** input parameters   argc  argv[]
** output parameters  void
** Returned value     0
****************************************************************/
int main(int argc, char* argv[])
{
    unsigned long int iNumber = 0 ;
    unsigned long int uliCountNumber = 0 ;
    printf("请输入iNumber:  ") ;
    scanf("%ld" , &iNumber) ;
    uliCountNumber =  oneNumber(iNumber) ;
    printf( "1~%d1的个数为: %d\n" , iNumber , uliCountNumber ) ;
    return 0;
}