1的数目

来源:互联网 发布:畅言软件下载 编辑:程序博客网 时间:2024/04/29 18:46

有这样一道题:1,2,3……n,这样写下去,求这一列数中,“1”出现的次数,记“1”的次数为f(n),求满足f(n)=n的最大的n。

看这题目有点像数论中的题目,学过数论的朋友一定会先在草稿纸上写

           9 ----- 1

         99 ----- 20

       999 ----- 300

……

10^n-1 ----- n*10^(n-1)       式①

一下子就找到规律了,我最初也是这样列的式子,但在编程的时候却总感觉不好动手,于是我把这些排成一列

          1

          2

    ……

           n

把数字对齐后,我很快发现,我只要将个位上的“1”,十位上的“1”……全部加起来,不就是题目的解么。而这也有规律,

个位上的“1” :每10个数就有一个“1”,不足10的时候,看其个位数是否大于等于1,代码表示为 n/10 + (n%10) > =1?1:0。

十位上的“1”:每100个数里面就有十个1,不足100的时候看其十位数是否大于1(取10)还是等于1(取个位数),还是小于1(取0),代码表示略

……

于是代码为:

ULONGLONG pw = 10;
m_nTimes = 0;// ”1“出现的次数

while(pw <= m_nNum)// m_nNum 为题目中的n
{
m_nTimes += (m_nNum/pw)*(pw/10);// 注意,不能化简为 m_nNum/10
if ((m_nNum%pw)/(pw/10) > m_nCnt)// m_nCnt ==1,还可以发散为m_nCnt 为两位数的情况
{
m_nTimes += pw/10;m_nTimes 
}
else if ((m_nNum%pw)/(pw/10) == m_nCnt)
{
m_nTimes += m_nNum%(pw/10) + 1;
}
pw *= 10;
}
if (m_nNum/(pw/10) > m_nCnt)
{
m_nTimes += pw/10;
}
else if (m_nNum/(pw/10) == m_nCnt)
{
m_nTimes += m_nNum%(pw/10) + 1;
}

这个算法的时间复杂度为O(lg(n))


第二问

由式①可以看出,当n小于10的时候,总f(n)小于n,而n>11时,总有f(n)>n,暂时我也没有从数学上推出这个值,希望有推出的朋友告知一声

由于这个函数不递增函数,因此不能用二分方法来查找最大的n,听说答案是1 111 111 110,




0 0