统计0到n之间1的个数

问题描述
给定一个十进制整数N,求出从1到N的所有整数中出现”1”的个数。

例如:N=2时 1,2出现了1个 “1” 。

N=12时 1,2,3,4,5,6,7,8,9,10,11,12。出现了5个“1”。

解题思路

1位数的情况:

在解法二中已经分析过,大于等于1的时候,有1个,小于1就没有。

2位数的情况:

N=13,个位数出现的1的次数为2,分别为1和11,十位数出现1的次数为4,分别为10,11,12,13,所以f(N) = 2+4。

N=23,个位数出现的1的次数为3,分别为1,11,21,十位数出现1的次数为10,分别为10~19,f(N)=3+10。

由此我们发现,个位数出现1的次数不仅和个位数有关,和十位数也有关,如果个位数大于等于1,则个位数出现1的次数为十位数的数字加1;如果个位数为0,个位数出现1的次数等于十位数数字。而十位数上出现1的次数也不仅和十位数相关,也和个位数相关:如果十位数字等于1,则十位数上出现1的次数为个位数的数字加1,假如十位数大于1,则十位数上出现1的次数为10。

3位数的情况:

N=123

个位出现1的个数为13:1,11,21,…,91,101,111,121

十位出现1的个数为20:10~19,110~119

百位出现1的个数为24:100~123

我们可以继续分析4位数,5位数,推导出下面一般情况:

假设N,我们要计算百位上出现1的次数,将由三部分决定:百位上的数字,百位以上的数字,百位一下的数字。

如果百位上的数字为0,则百位上出现1的次数仅由更高位决定,比如12013,百位出现1的情况为100~199,1100~1199,2100~2199,…,11100~11199,共1200个。等于更高位数字乘以当前位数,即12 * 100。

如果百位上的数字大于1,则百位上出现1的次数仅由更高位决定,比如12213,百位出现1的情况为100~199,1100~1199,2100~2199,…,11100~11199,12100~12199共1300个。等于更高位数字加1乘以当前位数,即(12 + 1)*100。

如果百位上的数字为1,则百位上出现1的次数不仅受更高位影响,还受低位影响。例如12113,受高位影响出现1的情况:100~199,1100~1199,2100~2199,…,11100~11199,共1200个,但它还受低位影响,出现1的情况是12100~12113,共114个,等于低位数字113+1。

实现代码

#include <iostream>
#include <cstring>
using namespace std;

int countOne(int n)
{
    int current = 0;
    int before = 0;
    int after = 0;
    int i = 1;
    int count = 0;
    while (n / i != 0)
    {
        current = n / i % 10;
        before = n / (i * 10);
        after = n - (n / i) * i;
        if (current > 1)
        {
            count += (before + 1) * i;
        }
        else if (current == 0)
        {
            count += before * i;
        }
        else if (current == 1)
        {
            count += before * i + after + 1;
        }

        i *= 10;
    }

    return count;
}

int main()
{
    int n;
    while (cin>>n)
    {
        cout<<countOne(n)<<endl;
    }

    return 0;
}
时间: 2024-08-30 15:37:39

统计0到n之间1的个数的相关文章

C语言编程中统计输入的行数以及单词个数的方法_C 语言

统计输入的行数 标准库保证输入文本流以行序列的形式出现,每一行均以换行符结束.因此,统计行数等价于统计换行符的个数. #include <stdio.h> /* count lines in input */ main() { int c, nl; nl = 0; while ((c = getchar()) != EOF) if (c == '\n') ++nl; printf("%d\n", nl); } 在该程序中,while 循环语句的循环体是一个 if 语句,它控

算法 递归 数据结构-2个1中间有1个数,2个n之间有n个数

问题描述 2个1中间有1个数,2个n之间有n个数 一组数1 1 2 2 3 3 4 4.....n n,经过操作后输出 使得 两个1之间有1个数 两个2之间有2个数 两点n之间有n个数 可以有0 对于确定n输出所有可能情况 解决方案 2N个数排成一行(每个数有2个), 2个1之间有1个数,2个2 之间有2个数,...2个N之间有N个数... 例312132 解决方案二: nXn方Xn3次方...Xn的n次方得到结果? 解决方案三: 如果是0的话那就是(n+1)的2分之(n + n 方)次方 解决

VC++6.0下面那段代码就读一个数怎么出乱码了

问题描述 VC++6.0下面那段代码就读一个数怎么出乱码了 20C int y;FILE* fp8=fopen(""E://dataoutput7.txt""r"");fprintf(fp8%d ""&y);fclose(fp8); TXT文件中就一个数字7,用这段代码怎么读出乱码了,求解决 解决方案 char ch[10];fprintf(fp8%s ""&ch);int y = atoi

java数组-Java计算排列组合 用java计算0,1,2,3这三个数每一行出现一个数,共有15行这样的数,如何求

问题描述 Java计算排列组合 用java计算0,1,2,3这三个数每一行出现一个数,共有15行这样的数,如何求 用java计算0,1,2,3这三个数每一行出现一个数,共有15行这样的数,如何求 解决方案 我觉得你的问题实在是很模糊,我刚好对java多线程懂一些,所以多问两句: 计算的是什么样的排列组合? 0,1,2,3 的 15行这样的数是哪样的数? 三个数? 每一行出现一个数? 麻烦解释一下~ 另外一个小建议:以后不要这样提问题啦~那些懂的人就算看到也会懒得回答的哦.提问要清晰明确~ 解决方

Linux下统计当前文件夹下的文件个数、目录个数_linux shell

1) 统计当前文件夹下文件的个数 复制代码 代码如下: ls -l |grep "^-"|wc -l 2) 统计当前文件夹下目录的个数 复制代码 代码如下: ls -l |grep "^d"|wc -l  3) 统计当前文件夹下文件的个数,包括子文件夹里的 复制代码 代码如下: ls -lR|grep "^-"|wc -l  4) 统计文件夹下目录的个数,包括子文件夹里的 复制代码 代码如下: ls -lR|grep "^d"

编程珠玑之生成0至n-1之间的k个不同随机序列的扩展问题 --2014人人网笔试题目

  <编程珠玑>中习题1.4的题目是:"如果认真考虑了习题3,你将会面对生成小于n且没有重复的k个整数的问题.最简单的方法就是使用前k个正整数.这个极端的数据集合将不会明显的改变位图方法的运行时间,但是可能会歪曲系统排序的运行时间.如何生成位于0至n - 1之间的k个不同的随机顺序的随机整数?尽量使你的程序简短高效."  解决这个问题可以使用以空间换时间的方式,基本的思想是 利用洗牌的原理,将n个数(0至n-1)按次序排好,依次让每个数和一个随机挑选出的位子进行互换,这样肯

统计一个二进制字符串中1的个数的算法

记得在吴军的<数学之美>中有一章讲到布尔代数和搜索引擎的索引.大概是讲通过一个二进制字符串来标识当前关键词在那些文档中出现过.二进制字符串中1的位置就是出现这个词文档的id. 如,一淘 对应一个二进制字符串 1010001.其中在1,5,7三个位置出现了1,说明文档id为1,5,7的文章包含词"一淘".但是在书中没有说如何统计1的个数和位置.现在我补充以下实现算法. 代码如下: #include <iostream> #include <math.h>

《剑指offer》-统计整数二进制表示中1的个数

题目描述 输入一个整数,输出该数二进制表示中1的个数.其中负数用补码表示. 直观思路就是把二进制表示从右往左统计1的个数.直接想到移位操作来迭代处理.坑点在于负数的移位操作会填充1.有人贴出了逻辑移位操作,但还是麻烦.直接按照int的位数,32或64,做这么多次移位操作就好了,每次移位操作累计是否为1.int的位数是32还是64,可以写一个函数来做到,而不是硬编码. class Solution { public: int NumberOf1(int n) { int cnt = 0; int

如何在正运行 SQL Server 7.0 的服务器之间传输登录和密码

server|服务器 SQL Server 7.0 数据转换服务 (DTS) 对象传输功能可在两台服务器之间传输登录和用户,但它不传输 SQL Server 验证登录的密码.要从一台运行 SQL Server 7.0 的服务器向另一台运行 SQL Server 7.0 的服务器传输登录和密码,请按照本文"在 Master 数据库中创建和运行存储过程"一节中的说明操作.您将在源服务器上创建 sp_help_revlogin 存储过程.此过程将生成一个脚本,您可以在目标服务器上运行该脚本,