zoukankan      html  css  js  c++  java
  • 几个一?

    一、题目

      给定一个十进制的正整数,写下从1开始,到N的所有整数,然后数一下其中出现“1”的个数。 要求: 写一个函数 f(N) ,返回1 到 N 之间出现的 “1”的个数。例如 f(12) = 5。 在32位整数范围内,满足条件的“f(N) =N”的最大的N是多少。

    二、设计思路

      思路来自于张欢龙的启发,就是将一个整数拆分,一位一位地求出“1”的个数,如451就是:

      45*1+1*1

    +4*10+1*10

    +0*100+1*100。

      先考虑个位,个位上数字0~9,总共出现过45个0~9,一个0~9有一个1,所以位45*1,而45个0~9外还有一个0~1,这时要再加上一个1;接着十位,每100个数里面均有*10到*19这10个出现1的数,所以十位也是0~9,但这里面的1要乘以10,4个0~9还多余一个0~5,所以也要加1,且乘以10;以此类推......

      如果某一位上是1,是不是情况就不一样了?如111,111情况如下:

     11*1+0+1

    +1*10+1+1

    +0*100+11+1

    ...

    +(m前面的十进制值*10m+m后面的十进制值+1(后面的值全为0的情况))

      就是当1出现时,这个多余的1的个数就为这一位后面的值。

      求f(N)=N的情况时,从2147483647开始向下逐一计算,时间过长,随便选了一个数即214748364,用前面的算法求出结果发现f(N)>N,所以正确的N一定比这个数小,所以从这开始计算。

    三、源代码

     1 //刘双渤,2015年6月3日
     2 //输入一个整数,输出出现1的个数
     3 #include <iostream>
     4 using namespace std;
     5 
     6 void main()
     7 {
     8     long num,rem,t,S;          //输入值,余数,十的倍数,一的总数
     9     long numS;
    10     cout<<"请输入一个整数:"<<endl;
    11     cin>>num;
    12 
    13     t = 1;
    14     S = 0;
    15     numS = num;
    16     while(numS != 0)
    17     {
    18         rem = numS % 10;
    19         numS = numS / 10;
    20         if(numS != 0)
    21         {
    22             S += numS * t;
    23         }
    24         
    25         if(rem > 1)
    26         {
    27             S += t;
    28         }
    29         else if(rem == 1)
    30         {
    31             S = S + num -numS * t* 10 - rem * t + 1;
    32         }
    33         t = t * 10;
    34     }
    35     cout<<"出现的“1”的个数为:"<<endl;
    36     cout<<S<<endl;
    37 
    38 
    39     for(long i = 214748364;i >= -214748364;i--)
    40     {
    41         t = 1;
    42         S = 0;
    43         numS = i;
    44         while(numS != 0)
    45         {
    46             rem = numS % 10;
    47             numS = numS / 10;
    48             if(numS != 0)
    49             {
    50                 S += numS * t;
    51             }
    52             if(rem > 1)
    53             {
    54                 S += t;
    55             }
    56             else if(rem == 1)
    57             {
    58                 S = S + i -numS * t* 10 - rem * t + 1;
    59             }
    60             t = t * 10;
    61         }
    62         if(S == i)
    63             break;
    64     }
    65     cout<<"满足条件的“f(N) =N”的最大的N是:"<<S<<endl;
    66 }
    View Code

    四、实验结果

      

    五、实验总结

     刚看到这个题目时,感觉很简单,然后就开始一个个值去算,用归纳法找规律,可越写发现情况越复杂,有点难!课上有人展示思路,下课再想,就有慢慢清晰,简单了起来。方法很多,却很需要这灵光一点,才能通透。

  • 相关阅读:
    (原创)在ER/Studio中使用宏把Attribute name复制到Definition
    Xming + PuTTY 在Windows下远程Linux主机使用图形界面的程序
    一个时间日期转换格式的小功能(Oracle)
    C#正则表达式整理备忘【转】
    【转】一篇好文,以在迷茫时阅读
    经常关注的、极具参考价值的网站收集(无限畅想版)
    中文分词备忘
    我心目中的编程高手
    网站推荐
    通过手机短信控制电脑
  • 原文地址:https://www.cnblogs.com/little-clever/p/4550579.html
Copyright © 2011-2022 走看看