统计从1到N中1的数目

1.Count1InAInteger()用来计算某一个数中1的个数,使用求余,然后再main中循环调用,但效率不高

1 #include <iostream>
2  using namespace std;
3
4 unsigned long Count1InAInteger(unsigned long n)
5 {
6 unsigned long iNum = 0;
7 while(n != 0)
8 {
9 iNum += (n % 10 == 1) ? 1 : 0;
10 n /= 10;
11 }
12 return iNum;
13 }
14
15 unsigned long main()
16
17 {
18 unsigned long iCount = 0;
19 unsigned long n = 0;
20 cout<<"输入你需要统计的数:";
21 cin>>n;
22 for (unsigned long i = 1; i <= n; i++)
23 {
24 iCount += Count1InAInteger(i);
25 }
26 cout<<"总共有"<<iCount<<"个'1'"<<endl;
27
28 }

2.先看看分析,编程之美上的:F(N)的计算方法: 假设 N=abcde,这里 a、b、c、d、e 分别是十进制数 N 的各个数位上的数字。如果要计算百位上出现 1 的次数,它将会受到三个因素的影响:百位上的数字,百位以下(低位)的数字,百位(更高位)以上的数字。

如果百位上的数字为 0,则可以知道,百位上可能出现 1 的次数由更高位决定,比如 12 013,则可以知道百位出现 1 的情况可能是 100~199,1 100~1 199,2 100~2 199,…,11 100~11 199,一共有 1 200 个。也就是由更高位数字(12)决定,并且等于更高位数字(12)×当前位数(100)。

如果百位上的数字为 1,则可以知道,百位上可能出现 1 的次数不仅受更高位影响,还受低位影响,也就是由更高位和低位共同决定。例如对于 12 113,受更高位影响,百位出现 1 的情况是 100~199,1 100~1 199,2 100~2 199,…,11 100~11 199,一共 1 200个,和上面第一种情况一样,等于更高位数字(12)×当前位数(100)。但是它还受低位影响,百位出现 1 的情况是 12 100~12 113,一共114 个,等于低位数字(123)+1。

如果百位上数字大于 1(即为 2~9),则百位上可能出现 1的次数也仅由更高位决定,比如 12 213,则百位出现 1 的可能性为:100~199,1 100~1 199,2 100~2 199,…,11 100~11 199,12 100~12 199,一共有 1 300 个,并且等于更高位数字+1(12+1)×当前位数(100)。通过上面的归纳和总结,我们可以写出如下的更高效算法来

1 /************************************************************************/
2 /* factor控制位数,计算各个位上的数目,然后相加 */
3 /************************************************************************/
4
5 #include <iostream>
6 using namespace std;
7 unsigned long sum1s(unsigned long n){
8 unsigned long count=0;
9 unsigned long factor=1;//控制位数
10 unsigned long lowerNum=0;
11 unsigned long currNum=0;
12 unsigned long higherNum=0;
13 while(n/factor!=0){
14 lowerNum = n-(n/factor)*factor; //求出比当前位低的数字
15 currNum = (n/factor)%10; //求出当前位的值
16 higherNum = n/(factor*10); //求出比当前位高的数字
17 switch(currNum)
18 {
19 case 0:
20 count += higherNum * factor;
21 break;
22 case 1:
23 count += higherNum * factor + lowerNum +1;
24 break;
25 default:
26 count += (higherNum+1)*factor;
27 break;
28 }
29 factor *=10;
30 }
31 return count;
32 }
33 int main(){
34 unsigned long n;
35 cout<<"大哥,你想算多少啊:";
36 cin>>n;
37 cout <<"从1到"<<n<<""<<sum1s(n)<<"个1"<<endl;
38 }
编程之美上说效率至少提高了40000倍…

posted @ 2011-04-08 15:37  lazycoding  阅读(821)  评论(0编辑  收藏  举报