求从1到n的数中,总共包含了多少个1

来源:互联网 发布:python 字典嵌套 list 编辑:程序博客网 时间:2024/05/15 09:29

首先容易想到的一种方法就是遍历这n个数,求出每个数中包含1的个数,然后加起来就ok了

[cpp] view plain copy
  1. //从1 到 n的正数中1出现的次数  
  2. #include <iostream>  
  3. using namespace std;  
  4.   
  5. //求n中包含几个1  
  6. int lmf(unsigned int n)  
  7. {  
  8.     int sum=0;  
  9.     while(n)  
  10.     {  
  11.         if(n%10 == 1)  
  12.         {  
  13.             sum++;  
  14.         }  
  15.         n = n/10;  
  16.     }  
  17.     return sum;  
  18. }  
  19.   
  20. int bxy(unsigned int n)  
  21. {  
  22.     int sum = 0;  
  23.     for(unsigned int i=1; i <= n; ++i)  
  24.     {  
  25.         sum += lmf(i);  
  26.     }  
  27.     return sum;  
  28. }  
  29.   
  30.   
  31. void main()  
  32. {  
  33.     cout << bxy(11) <<endl;  
  34. }  


 

但是这样做了好多无用功,试试对21345做个分析

首先把数字分为两部分:

1到1345

1346到21345

首先求从1346到21345

考虑最高位引入的1的个数,从10000到19999,一共10^4个,就是10的(length-1)次方。

由后四位引入的1的个数,计算如下:

2*10的3次方,

其中2指的是:万位上的两种选择0或者2

10的三次方指的是:后四位中有一位是1,其他三位从0到9十个数字任意选。

1到1345 使用递归求解。

程序如下:

[cpp] view plain copy
  1. #include <iostream>  
  2. using namespace std;  
  3.   
  4.   
  5.   
  6. int Pow10(unsigned int n)  
  7. {  
  8.     int result = 1;  
  9.     for(unsigned int i=0; i<n; i++)  
  10.     {  
  11.         result *= 10;  
  12.     }  
  13.     return result;  
  14. }  
  15.   
  16. int lmf(const char *strN)  
  17. {  
  18.     if(!strN || *strN<'0' || *strN>'9' || *strN=='\0')  
  19.     {  
  20.         return 0;  
  21.     }  
  22.   
  23.     int firstDigit = *strN-'0';  
  24.     unsigned int length = static_cast<unsigned int>(strlen(strN));  
  25.     //如果只有一位数,而且还是0,那就是0 了。。。  
  26.     if(length==1 && firstDigit==0)  
  27.     {  
  28.         return 0;  
  29.     }  
  30.     //如果只有一位数,但是大于0,那肯定包含一个1  
  31.     if(length==1 && firstDigit>0)  
  32.     {  
  33.         return 1;  
  34.     }  
  35.   
  36.     //这里变量代表:10000到19999 这期间由于第一位引入的1的个数  
  37.     int numFirstDigit = 0;  
  38.     //如果最高位不是1,例如:23415,则由最高位引入的1的个数就是从10000到19999:也就是10^(5-1)  
  39.     if(firstDigit>1)  
  40.     {  
  41.         numFirstDigit = Pow10(length-1);  
  42.     }  
  43.     //如果第一位是1,例如12345.则由于第一位而引入的    1的个数就是从10000到12345,一共2346  
  44.     if(firstDigit == 1)  
  45.     {  
  46.         numFirstDigit = atoi(strN+1)+1;  
  47.     }  
  48.   
  49.     //这个变量计算的是:由01346到21345除了第一位剩下其他为所引入的1的个数,  
  50.     //也就是说第一位只能取0或者2------firstDigit  
  51.     //剩下的四位中选出一位是1,即4种选法----------length-1  
  52.     //剩下的三位可以自由选择------------10^(length-2)  
  53.     //所以计算如下:  
  54.     int numOtherDigit = firstDigit * (length-1) * Pow10(length-2);  
  55.   
  56.     //剩下的数字也就是从1到1345,递归调用此函数  
  57.     int numRecursive = lmf(strN+1);  
  58.   
  59.     //返回三部分的和  
  60.     return numFirstDigit+ numOtherDigit +numRecursive;  
  61. }  
  62.   
  63. int bxy(int n)  
  64. {  
  65.     if(n <= 0)  
  66.     {  
  67.         return 0;  
  68.     }  
  69.     char strN[50];  
  70.     sprintf(strN,"%d",n);  
  71.     return lmf(strN);  
  72. }  
  73.   
  74. void main()  
  75. {  
  76.     cout << bxy(20) <<endl;  
  77. }  

0 0