整数中x出现的次数(1-n中x出现的次数)

来源:互联网 发布:成都富士康java 编辑:程序博客网 时间:2024/05/25 08:11

整数中x出现的次数


  欢迎大家阅读我的博客,如果有错误请指正,有问题请提问,我会尽我全力改正错误回答问题。在次谢谢大家。


实验环境


  • 语言c/c++
  • 编译器devc++5.11/5.40


实验内容与要求


输入输入为一行,为一个整数 n (1 ≤ n ≤ 10^9),为一个整数 x (0 ≤ x ≤ 9)。输出将从 1 到 n (包括 1 和 n) 的每一个数的十进制表示中的x个数 ,输出x个数总数。样例输入2499 0样例输出689总时间限制: 1000ms 内存限制: 256000kB


目录


  • 整数中x出现的次数
    • 实验环境
    • 实验内容与要求
  • 目录
  • 实验解析
    • 思路
      • 前言
      • 举例
      • 分类讲解
        • 对应位正好就等于要找的数
        • 对应位正好就大于要找的数
        • 对应位正好就小于要找的数
        • 0
        • 总结
    • 定义说明
    • 函数说明
      • 功能函数
        • 获取输入
        • 获取结果
      • 主函数
    • 结果展示
  • 附录
    • 相关资料
    • 源代码
      • 第一版
      • 第二版


实验解析

思路


前言

  解决这类问题,最好的方法是,先构造出对应的数学模型,然后根据数学模型来编写程序,这样事半功倍。像我这样的小白,第一次总是手忙脚乱的上来就编,边写边想,极容易出错,也会使自己十分紧张,打乱节奏。希望看到本文的童鞋们引以为戒。

举例

  这道题呢,我的想法是一位一位的看,从高位开始还是低位开始影响不大。
  比如,1234这个数,找3出现的次数,从高位开始:

  • 1<3,又是最高位说明 3 不会出现在千位,出现次数 + 0*1000 + 0*100
  • 2<3,考虑到高位是1,出现次数+1*100 +0*10
  • 3=3,高位为2,出现次数+ 12*10 + 4*1+1
  • 4>3,高位为3,出现次数+ (123+1) * 1
    有没有找到些规律呢?

分类讲解

  没明白的话,我们来讨论一些简单的例子,懂了的童鞋可以跳过。比如,1111这个数,找1出现的次数,从高位开始:

对应位正好就等于要找的数

  • 首位正好就等于要找的数,这时因为没有高位了,让我们可以只思考低位对其影响。1出现千位的次数就等于低位111+1。这个1代表什么呢?1000。那111呢?1001,1002···1111,是不是有些明白了呢
  • 然后是次高位,也正好是1,低位如何考律我们已经明白了,就是11+1嘛。这时有高位的问题,高位是1,所以要加上1*100,这个100代表什么呢?100,101···199。这时候有人问了我们这一步步算的是啥?第一步算的是1出现在千位的次数,这步算的是1出现在百位的次数,这样,每位出现多少次加到一起不就是总量了么。
  • 十位也一样不再过多赘述 110+1+1
  • 个位就不再有低位所以就是111
    有没有找到些规律呢?这是相等时的算法

对应位正好就大于要找的数

  当大于要找的数时低位的影响就消失了,比如121 找1 十位肯定经历了 110 111 所以 计算十位时相当于(1+1)*10

对应位正好就小于要找的数

  小于要找的数也不用考虑低位,因为压根就没有出现 101 找1 十位 就是 1*10

‘0‘

  这是我们发现0这个数字不符合现有情况,所以单独考虑

  • 当前是0,高位不可能是零,最低是1,与其他数相比整体位移,高位-1乘上当前位,以及低位+1
  • 当前大于,高位可能是零,与其他数相比整体位移,高位乘上当前位

总结

每位的算法分为两部分:
1. 非零数字分三类

 1. 小于要找的数:只看高位乘上当前位,例如4321 百位 4*100 2. 大于要找的数:只看高位+1乘上当前位,例如4321 百位 (4+1)*100 3. 等于要找的数:要考虑高位乘上当前位,以及低位+1,例如4321 百位 4*100+21+1

2. 零分两类

1. 当前是0,高位不可能是零,最低是1,与其他数相比整体位移,高位-1乘上当前位,以及低位+12. 当前大于,高位可能是零,与其他数相比整体位移,高位乘上当前位


定义说明


#include <iostream>//输入输出#include <string.h>//字符串using namespace std;//函数声明inline getnum(long &c,int &x);//输入long getcount(long c, int x );//获取结果


函数说明



功能函数

获取输入

inline getnum(long &c,int &x){//获取数 换成赛艇的数字     cin>>c; //获取n    cin>>x;//获取x}


获取结果

long getcount(const long c,const int x ){    long high = c,temp,low;    long count =0;    int curr,i = 10;    if(x == 0){        while(high>0){              high = c/i;//高位            temp = c%i;            curr = temp /(i/10);//当前位            low = temp %(i/10);//低位            if(curr == 0){                      count +=( high-1)*(i/10)+low+1;            }else if(curr > 0){                 count += high *(i/10);            }            i*=10;        }    }else{        while(high>0){              high = c/i;//高位            temp = c%i;            curr = temp /(i/10);//当前位            low = temp %(i/10);//低位            if(curr == x){                      count += high*(i/10)+low+1;            } else if(curr > x){                                count += (high+1)*(i/10);            }else{                      count += high*(i/10);            }            i*=10;        }    }    return count;}

  从低位开始,与之前分析相反,童鞋们正好可以自己验算一遍。


主函数


main(){    long num;    int x;     getnum(num,x);     num = getcount(num,x);      cout<<num<<endl;}


结果展示


测试结果


附录

相关资料

  1. 第一版参考资料
  2. 第二版参考资料


源代码


第一版

#include <iostream>#include <string.h>using namespace std;//函数声明inline getnum(long &c,int &x);long getcount(long c, int x );main(){    long num;    int x;     getnum(num,x);     num = getcount(num,x);      cout<<num<<endl;} inline getnum(long &c,int &x){//获取数 换成赛艇的数字     cin>>c;     cin>>x;}long getcount(const long c,const int x ){    long high = c,temp,low;    long count =0;    int curr,i = 10;    if(x == 0){        while(high>0){              high = c/i;            temp = c%i;            curr = temp /(i/10);            low = temp %(i/10);            if(curr == 0){                      count +=( high-1)*(i/10)+low+1;            }else if(curr > 0){                 count += high *(i/10);            }            i*=10;        }    }else{        while(high>0){              high = c/i;            temp = c%i;            curr = temp /(i/10);            low = temp %(i/10);            if(curr == x){                      count += high*(i/10)+low+1;            } else if(curr > x){                                count += (high+1)*(i/10);            }else{                      count += high*(i/10);            }            i*=10;        }    }    return count;}

第二版

#include <iostream>#include <string.h>using namespace std ;class Solution {public:    long n;    int x;    long NumberOf1Between1AndN_Solution(){        long ones = 0;        if(x!=0)            for (long m = 1; m <= n; m *= 10)                ones += (n/m + 9-x) / 10 * m + (n/m % 10 == x) * (n%m + 1);        else            for (long m = 1; m <= n; m *= 10)                ones += (n/m -1) / 10 * m + (n/m % 10 == 0) * (n%m + 1);        return ones;    }    inline getnum(){//获取数 换成赛艇的数字         cin>>n;         cin>>x;    }};main(){    long num;    int x;     Solution s;    s.getnum();     num = s.NumberOf1Between1AndN_Solution();      cout<<num<<endl;    }
原创粉丝点击