AcWing.338. 计数问题

2024-01-27 21:04
文章标签 计数问题 acwing.338

本文主要是介绍AcWing.338. 计数问题,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

给定两个整数 a 和 b,求 a 和 b 之间的所有数字中 0∼9 的出现次数。

例如,a=1024,b=1032,则 a 和 b 之间共有 9 个数如下:

1024 1025 1026 1027 1028 1029 1030 1031 1032

其中 0 出现 10 次,1 出现 10 次,2 出现 7 次,3 出现 3 次等等…

输入格式

输入包含多组测试数据。

每组测试数据占一行,包含两个整数 a 和 b。

当读入一行为 0 时,表示输入终止,且该行不作处理。

输出格式

每组数据输出一个结果,每个结果占一行。

每个结果包含十个用空格隔开的数字,第一个数字表示 0 出现的次数,第二个数字表示 1 出现的次数,以此类推。

数据范围

0<a,b<100000000

输入样例:
1 10
44 497
346 542
1199 1748
1496 1403
1004 503
1714 190
1317 854
1976 494
1001 1960
0 0
输出样例:
1 2 1 1 1 1 1 1 1 1
85 185 185 185 190 96 96 96 95 93
40 40 40 93 136 82 40 40 40 40
115 666 215 215 214 205 205 154 105 106
16 113 19 20 114 20 20 19 19 16
107 105 100 101 101 197 200 200 200 200
413 1133 503 503 503 502 502 417 402 412
196 512 186 104 87 93 97 97 142 196
398 1375 398 398 405 499 499 495 488 471
294 1256 296 296 296 296 287 286 286 247

 思路:求出每一位数字中0~9出现的次数

假设一个数为七位数 abcdefg ,从中求出1~abcdefg这些数字中1出现的次数,即所有位数上1出现的次数的和

比如求1在第四位上出现的次数:即求有多少如 _ _ _ 1 _ _ _ 这样的数是在范围之内的

        (1)当前三位从001取到abc - 1 ,那么前三位已经决定了这个数一定是小于最大值abcdefg的,那么我们后三位可以随便取得,即从000取到999,那么这种情况有abc * 1k 种选法

        (2)当前三位取abc,那么前三位已经是可取的最大值,那么要进一步进行分类讨论

                1.当第四位d < 1,也就是abcdefg是永远小于abc1_ _ _的,那么这种情况取1的可能为0

                2.当第四位d = 1,也就是这个数为abc1_ _ _,那么前四位已经是可取的最大的,后三位就只能去000~efg,只有这样才能保证不超范围,那么有 efg + 1 种选法

                3.当第四位d > 1,也就是abc1_ _ _前四位并没有取到最大值,那么后三位随便取也可以保证在范围内,即取000 ~ 999,那么有 1k 种情况

最后,比如我们要求数A到数B之间的计数,那么我们只需要用1~B减去1~A,就能得到A~B之间的计数 

注:当需要计数的数字在第一位的时候,就不需要讨论情况(1)了 

#include<iostream>
#include<vector>
using namespace std;int get(vector<int> num, int l, int r)	//求i前面这些位数字组成的数字(对应第一种情况)
{int res = 0;for (int i = l; i >= r; i--) {res = res * 10 + num[i];}return res;
}int power10(int x) {	//求10的x次方int res = 1;while (x--)res *= 10;return res;
}int count(int n, int x) {	//1到n中统计x的出现次数if (!n)return 0;	//如果n等于0直接返回vector<int> num;while (n) {			//获取n的每一位数num.push_back(n % 10);n /= 10;}n = num.size();	//让n等于自己的位数int ans = 0;	//ans存答案for (int i = n - 1 - !x; i >= 0; i--) {		//i从最高位开始枚举(计算每一位上数字组成情况),且当最高位为0的时候,从第二位开始枚举if (i < n - 1) {	//如果枚举到的不是最高位ans += get(num, n - 1, i + 1) * power10(i);	//i的前面这些位数字乘上10的i次方(所有的组成方法)if (!x) ans -= power10(i);	//如果计算的是0的次数,那么要减去一次10的i次方(从001开始,少了一次10的i次方)}if (num[i] == x)ans += get(num, i - 1, 0) + 1;	//如果这一位数字等于计算数组,数量为后面这些位组成的数字加上1else if (num[i] > x) ans += power10(i);	//如果这一位是大于当前求的数字的,那么就加上10的i次方}return ans;
}int main() {int a, b;while (cin >> a >> b, a || b) {		//a和b不一定谁更小if (a > b)swap(a, b);for (int i = 0; i < 10; i++)cout << count(b, i) - count(a - 1, i) << " ";puts("");}return 0;
}

这篇关于AcWing.338. 计数问题的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/651480

相关文章

数位统计DP——AcWing 338. 计数问题

数位统计DP 定义 数位DP(Digital DP)是一种用于解决与数字的数位相关问题的动态规划算法。它将数字的每一位看作一个状态,通过转移状态来计算满足特定条件的数字个数或其他相关统计信息。 运用情况 统计满足特定条件的数字个数,例如在给定范围内有多少个数字满足某些数位特征。计算数字的某个数位上的特定统计信息,如出现的数字频率等。解决与数字排列、组合相关的问题。 注意事项 数位DP的

质数计数问题求解

质数计数问题求解 题目 leetcdoe204 计数质数:https://leetcode.cn/problems/count-primes 给定整数 n ,返回 所有小于非负整数 n 的质数的数量 。 示例1: 输入:n = 10 输出:4 解释:小于 10 的质数一共有 4 个, 它们是 2, 3, 5, 7 。 示例 2: 输入:n = 0 输出:0 示例

UVA 11645 - Bits(数论+计数问题)

题目链接:11645 - Bits 题意:给定一个数字n,要求0-n的二进制形式下,连续11的个数。 思路:和 UVA 11038 这题类似,枚举中间,然后处理两边的情况。 不过本题最大的答案会超过longlong,要用高精度,不过借鉴http://www.cnblogs.com/TO-Asia/p/3214706.html这个人的方法,直接用两个数字来保存一个数字,这样能保

UVA 11038 - How Many O's?(计数问题)

题目链接:11038 - How Many O's? 题意:求[a.b]之间,0出现的次数。 思路:一开始一直往数位DP上去想,结果发现挺复杂的。。 把问题先转化为求0 - num的个数,在用到b的个数减去到a的个数 其实只要利用计数的乘法和加法原理,把数字对应的每一位的分成左右两边,利用乘法原理求总数,在用加法原理把所有的总数加起来就是总情况数。那么讨论一下分成两边

【数论】计数问题的几种基本方法

一、计数原理 加法原理:n个方法,每个方法有Pi种方案,那么一共方案数为P1 + P2 + P3... + Pn 乘法原理:一件事情有n个步骤,每个步骤需要pi种方案,那么一共有P1 * P2 * P3 * ... * Pn种方案。 容斥原理:集合A,B,C。|A U B U C| = |A| + |B| + |C| - |AB| - |AC| - |BC| + |ABC|。依次类推。 基

UVA 10253 - Series-Parallel Networks(数论+计数问题+递推)

题目链接:10253 - Series-Parallel Networks 白书的例题。 这题也是需要把问题进行转化,一个并联可以分为几个串联,然后串联可以分成边。 如此一来,最后叶子结点种数会是n,问题转化为去分配叶子结点,使得总和为n。 书上有两种方法,一种直接去递归,利用组合数学的方式去计算答案。 一种是推出递推式: 设dp[i][j]为一共j个

UVA 12508 - Triangles in the Grid(计数问题)

12508 - Triangles in the Grid 题目链接 题意:给定一个n∗m格子的矩阵,然后给定A,B,问能找到几个面积在A到B之间的三角形。 思路:枚举每一个子矩阵,然后求[0,A]的个数减去[0,B]的个数就是答案,然后对于每个子矩阵个数很好求为(n−r+1)∗(m−c+1)。关键在于怎么求每个子矩阵的符合个数。 想了好久,参考别人题解才想出来,分3种情况讨论:

计数问题--抽屉原理(鸽笼原理)

定理:(鸽笼原理)若有 n 只鸽子住进 m(n>m) 个鸽笼,则存在一个鸽笼至少住进[(n-1)/m]+1只鸽子,[x]表示小于等于x的最大整数。 注意:1.鸽笼原理只提供了存在性证明。            2.使用鸽笼原理,必须能够正确识别鸽子(对象)和鸽笼(某类要求的特征),并能够计算出鸽子数和鸽笼数。   例: 某一制造铁盘的工厂,由于设备和技术的原因只能将生产盘子的重量控制在

leetcode——用位运算来做2的幂次方和比特位计数问题

231.给定一个整数,编写一个函数来判断它是否是 2 的幂次方。 示例 1: 输入: 1 输出: true 解释: 20 = 1 示例 2: 输入: 16 输出: true 解释: 24 = 16 示例 3: 输入: 218 输出: false 思路: 可以用mod去摸运算来做,也可以用 l o g 2 log_{2} log2​得到int数 但是最快捷的方法还是用位运算,因为不管是2

树与图的一些计数问题(图论学习总结部分内容)

文章目录 前言七、树与图的一些计数问题(偏数学)容斥原理知识点例题 e g 1 : eg1: eg1: 完全子图染色问题 e g 2 : eg2: eg2: D A G DAG DAG计数 生成树计数知识点例题 环计数问题练习题 前言 由于图论学习总结内容过多,全放在一篇博客过于冗长现进行拆分,本文是树与图的一些计数问题部分,其他部分地址见:图论学习总结(For XCPC