http://ac.nbutoj.com/Problem/view.xhtml?id=1475
  • [1475] Bachelor

  • 时间限制: 1000 ms 内存限制: 65535 K
  • 问题描述
  • 炎热的暑期集训就要结束了,在这短短的20天,大家都很努力,因为很多都是光棍嘛。balabala 所以 Marknoon 先森一直耿耿于怀,毕竟他也是单身嘛。 有一天,Marknoon 先森看着一串数字,发现了那个跟他同命相连的数字1,所以他就开始无聊起来,想知道从数字1到数字N,一共出现了几个1。 例如N=12,则1的个数为5,出现1的数字分别为1,10,11,12。
  • 输入
  • 输入一个数N(1 <= N <= 2147483647)。
  • 输出
  • 输出从1到N中所有数字里出现 1 的个数。
  • 样例输入
  • 3
    13
    123
  • 样例输出
  • 1
    6
    57
  • 思路:
  • 解法1:按位置计算,即分别计算个位,十位,百位,千位 。。。的 1 出现的次数,然后将他们的个数和输出

  • 这里以 2145 为例进行说明: 个位为 1 的情况 : _ _ _ 1  横线部分 可以是  000 到 214 的任意数字   所以个位   一共有 215个 1 ------- (214 + 1)

          • 十位为 1 的情况: _ _ 1 _  横线部分 可以是 000  到 219 的任意数字  十位 一共有 220 个 1   -------  (21 +1)*10

            百位为 1 的情况: _ 1 _ _  横线部分 可以是 000  到 245 的任意数字  百位 一共有 246 个 1   ------    2 * 100 +45 +1

          • 千位为 1 的情况:  1 _ _ _  横线部分 可以是 000  到 999 的任意数字  千位 一共有 1000 个 1  ------  (0 + 1)* 1000
  • 当然 还有 为 0 的情况   如果是 2105 的话  则  有  21* 10 ----  十位 有 210 个 1
  • 规律应该可以找到了吧!!!
  •  #include <iostream>
    #include <stdio.h>
    #include <math.h>
    #include <string.h>
    #include <vector> using namespace std; int getNum(int *a,int i,int j) //得到a数组里面[i,j]区间构成的数
    {
    int sum=;
    for(;i<=j;i++) sum=*sum+a[i];
    return sum;
    } int main()
    {
    char str[];
    int a[];
    __int64 p[]={,,,1e3,1e4,1e5,1e6,1e7,1e8,1e9,1e10,1e11,1e12};
    while(~scanf("%s",str))
    {
    int len = strlen(str);
    int i,left,right;
    for(i=;i<len;i++) a[i]=str[i]-'';
    __int64 sum = ;
    for(i=;i<len;i++)
    {
    left = getNum(a,,i-);;
    if(a[i]>)
    {
    sum+=(left+)*p[len--i]; //如果数字大于1 则用左边 a[0,i-1] 构成的数 加1 乘上 10的(右边位数)次方
    }
    else if(a[i]==)
    {
    right = getNum(a,i+,len-);
    sum+=left*p[len--i]+right+; //如果数字等于1 则用左边 a[0,i-1] 构成的数 乘上 10的(右边位数)次方 后 加上 右边a[i,len-1] 构成的数 再加上1
    }
    else if(a[i]==)
    {
    sum+=left*p[len--i]; //如果数字等于0 则用左边 a[0,i-1] 构成的数 直接乘上 10的(右边位数)次方
    }
    }
    printf("%I64d\n",sum); }
    return ;
    }

    解法二:先写断暴力代码测试用:

  • 找到规律输    9:1
  • 99:20
  • 999:300
  • 9999:4000
      • 99999 : 50000
    •  #include<iostream>
      #include<algorithm>
      #include<stdio.h>
      #include<math.h>
      #include<string.h>
      using namespace std;
      int main()
      {
      int i;
      __int64 a[]={,};
      int b[]={};
      char str[];
      a[]=;
      for(i=;i<;i++)
      {
      int cnt=;
      if(i%==)
      cnt++;
      if(i/==)
      cnt++;
      b[i]+=b[i-]+cnt;
      }
      __int64 temp=; __int64 pow[]={,,,1e3,1e4,1e5,1e6,1e7,1e8,1e9,1e10,1e11,1e12}; for(i=;i<=;i++)
      {
      a[i]=i*pow[i-];
      } while(~scanf("%s",str))
      {
      int len=strlen(str);
      __int64 s=;
      for(i=;i<len;i++)
      {
      temp = str[i] - '';
      s=*s+temp;
      }
      __int64 sum=;
      for(i=;i<len-;i++)
      if(str[i]!='')
      {
      int p=len-i;
      if(str[i]=='')
      {
      s=s%pow[p-];
      sum+=a[p-]+s+;
      }
      else
      sum+=pow[p-]+a[p-]*(str[i]-'');
      }
      sum+=b[s%];
      printf("%I64d\n",sum);
      }
      return ;
      }

noj [1475] Bachelor (找1的个数)的更多相关文章

  1. NBUT [1475] Bachelor

    [1475] Bachelor http://acm.nbut.cn:8081/Problem/view.xhtml?id=1475 时间限制: 1000 ms 内存限制: 65535 K 问题描述 ...

  2. 找出数组中出现次数超过一半的数,现在有一个数组,已知一个数出现的次数超过了一半,请用O(n)的复杂度的算法找出这个数

    找出数组中出现次数超过一半的数,现在有一个数组,已知一个数出现的次数超过了一半,请用O(n)的复杂度的算法找出这个数 #include<iostream>using namespace s ...

  3. search for a range(找出一个数在数组中开始和结束位置)

    Given an array of integers sorted in ascending order, find the starting and ending position of a giv ...

  4. 找出n个数中出现了奇数次的两个数

    如果是找只出现了奇数次的一个数, 那么我们从头异或一遍就可以. 那么如何找出现了奇数次的两个数呢? 首先我们还是从头异或一遍, 然后结果肯定不为0, 对于异或出来的结果, 如果这个数的某一位是1, 说 ...

  5. 3sum(从数组中找出三个数的和为0)

    Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0? Find all un ...

  6. 找出N个数中最小的k个数问题(复杂度O(N*logk))

    这是一个经典的算法题,下面给出的算法都在给定的数组基础上进行,好处时不用分配新的空间,坏处是会破坏原有的数组,可以自己分配新的空间以避免对原有数组的破坏. 思路一 先直接排序,再取排序后数据的前k个数 ...

  7. SDUT OJ 1221 亲和数 (找出某个数n所有的因子数,只需要暴力:2->sqrt(n) 即可 )

    亲和数 Time Limit: 1000ms   Memory limit: 65536K  有疑问?点这里^_^ 题目描述 如果a的因子和等于b,b的因子和等于a,且a≠b,则称a,b为亲和数对. ...

  8. 【算法学习笔记】Meissel-Lehmer 算法 (亚线性时间找出素数个数)

    「Meissel-Lehmer 算法」是一种能在亚线性时间复杂度内求出 \(1\sim n\) 内质数个数的一种算法. 在看素数相关论文时发现了这个算法,论文链接:Here. 算法的细节来自 OI w ...

  9. 找大于等于一个数的最小的2^n

    最近看hashmap源码时,发现给定初始capacity计算threshold的过程很巧妙. 1 static final int tableSizeFor(int cap) { 2 int n = ...

随机推荐

  1. 关于C++需要加强学习的几点内容

    1.C++ effective指导原则 2.C++标准库 3.数据结构算法 4.C++设计模式 5.shell脚本 6.python

  2. 在 Ubuntu 16.04 中安装谷歌 Chrome 浏览器

    进入 Ubuntu 16.04 桌面,按下 Ctrl + Alt + t 键盘组合键,启动终端. 也可以按下 Win 键(或叫 Super 键),在 Dash 的搜索框中输入 terminal 或&q ...

  3. xilinx 网站资源导读

    [经验整理.01]Xilinx网站资源导读 ISE11版 标签:  ISE  Xilinx  入门  资源  2009-09-01 20:41 序 虽然自己也曾想过,但如果不是向农要求,把曾经写过的文 ...

  4. ckeditor

    去掉编辑器的下边栏 在config.js中加入: config.removePlugins = 'elementspath'; config.resize_enabled = false; 就ok了 ...

  5. ASP.NET笔记之 ListView 与 DropDownList的使用(解决杨中科视频中的问题)

    1.Repeater用来显示数据.ListView用来操作数据 InsertItemTemplate和updateItemTemplate**Eval(显示数据)和Bind(双向绑定:不仅是需要展现, ...

  6. 比较ASP生成静态HTML文件的几种方法

    将动态页面转换生成静态Html文件有许多好处,比如生成html网页有利于被搜索引擎收录(特别是对接受动态参数的页面).前台访问时,脱离了数据访问,减轻对数据库访问的压力,加快网页打开速度. 当然,凡事 ...

  7. java中的拷贝文件FileChannel

    以前用Java拷贝文件,只知道写byte数组循环拷贝,今天知道了可以用FileChannel进行拷贝,上代码: 下边是传统的byte数组拷贝方法 </pre><pre name=&q ...

  8. hive metastore异常 org.apache.thrift.protocol.TProtocolException: Missing version in readMessageBegin, old client

    hiveserver2的端口是10000hive.metastoe.uris 的端口9083改为10000之后 beelien 连接hiveserver2报错 Error: Could not ope ...

  9. Innosetup打包自动下载.net framework 动态库及替换卸载程序图标.

    在使用了一段时间微软自带的安装包打包工具后,总感觉不太顺利,于是便想着找一种更简单稳定的打包工具,这类工具其实还不少,最终经过各种考量,我们选择了 InnoSetup , 该工具是一个完全免费的Win ...

  10. RSA算法使用介绍

    http://www.cnblogs.com/AloneSword/p/3326750.html RSA是目前最有影响力的公钥加密算法,该算法基于一个十分简单的数论事实:将两个大素数相乘十分容易,但那 ...