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

相关文章

python-计数问题

题目描述 试计算在区间 1 到 n 的所有整数中,数字 x(0≤x≤9)共出现了多少次?例如,在 1 到 11 中,即在 1,2,3,4,5,6,7,8,9,10,11 中,数字 1 出现了 4 次。输入格式 2 个整数 n,x,之间用一个空格隔开。输出格式 1 个整数,表示 x 出现的次数。样例 #1样例输入 #1 11 1样例输出 #1 4提示 对于 100% 的数据,1≤n≤106,0≤x≤

ES多键聚合桶个数计数问题

ES多键聚合桶个数计数问题 开发验证过程中,ElasticSearch聚合时不显示桶的个数,在进行数据核对时非常麻烦。这里有几个解决方案: java代码中计数     java代码中发送查询后,返回response,buckets返回是一个数组,可以获取数组的大小,即聚合桶的数量。我知道这个解决方案可能被喷。 ES使用查询语句计数 GET cn_order*/_search{"siz

1423. [NOIP2013]计数问题

【题目描述】       试计算在区间1到n的所有整数中,数字x(0≤x≤9)共出现了多少次?例如,在1到11中,即在1、2、3、4、5、6、7、8、9、10、11中,数字1出现了4次。 【输入格式】        输入共1行,包含2个整数n、x,之间用一个空格隔开。 【输出格式】       输出共1行,包含一个整数,表示x出现的次数。 【样例输入】 11 1 【样例输出】 4 【提示】

数位统计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种情况讨论: