找“1”的个数

1,题目

输入一个十进制的数,输出

    (1)给定n,求出从1到n的所有整数中1的个数。(暂用用f(n)表示)
    (2)求满足n=f(n)的最大整数(1除外)。

2,思路

首先想到的是字符串匹配的方法,但是这个方法比较麻烦,不简便.

然后实行的方法是把数字排列出来找规律,开始找的规律是

f(10)=2,f(11)=4,f(12)=5......

f(20)=11,f(21)=12,f(22)=12........

.........

即当某位上的数等于1和不等于1时有所不同,当它上一位上等于1时,f(n)会规律性增加。但是这个规律仍是局限于数字的大小。

后来经过讨论,得出的比较合适的方法是根据一个数不同的位数和它周围位数的关系来总结规律。

以abcde为例,

最高位a,出现1的次数:10000~19999跨度为10000;

第二位b,出现1的次数:1000~1999.跨度为1000;

第三位c,出现1的次数:100~199跨度为100;

。。。。

第0~n -1位组成的数字乘以跨度,然后再根据当前位是大于1,等于1,等于0来加上一个可变的数值。

具体就是,若当前位大于1,则加上跨度;若当前位等于1,则加上该位之后的尾数;若当前位等于0,则加0;具体在个位上时有不同。

3,代码与截图

非递归算法:

#include<iostream>
using namespace std;


int COUNT(int n)
{
    int m = 1;

    int count= 0;
    cout << "输入想要查询的十进制正整数:";
    cin >> n;
    while (n >= m)
    {
        int k = 10 * m;
        switch((n%k) / m)
        {
        case 0:
            count += (n / k)*m;
            break;
        case 1:
            count += (n / k)*m;
            count += n%m + 1;
            break;
        default:
            count += (n / k + 1)*m;
        }
        m = m * 10;
    }
    return count;
}

void main()
{
    int n=0;
    cout << "‘1’的个数为:" <<COUNT(n)<< endl;
}
View Code

递归算法:

#include<iostream>
using namespace std;

int main()
{
    int count = 0, i, N, temp;
    cout << "输入一个十进制的数 :";
    cin >> N;
    for (i = 1; i <= N; i++)
    {
        temp = i;//这个地方用个临时变量记录i的值
        while (temp != 0)
        {
            count += (temp % 10 == 1) ? 1 : 0;
            temp /= 10;
        }
        if (count == i)
        {
            cout << "n=f(n)是:"<<i << endl;
        }
    }
    cout << "‘1’的个数为:" << count << endl;
    return 0;
}
View Code

 

4,总结

递归算法来解决问题减少了很多麻烦,很简便。

实现程序首先要融入和了解数学思维。循环等编程方法都是从数学积累而来。

要得到数学规律要基于大量的事实基础,规律要找对找准。

 

posted @ 2015-05-30 21:50  so#what  Views(187)  Comments(0Edit  收藏  举报