[AcWing 338] 计数问题

image
image

不使用 vector 的写法


点击查看代码
#include<iostream>
#include<cmath>

using namespace std;

// 计算 n 有多少位 
int dgt(int n)
{
	int res = 0;
	while (n) {
		res ++;
		n /= 10;
	}
	return res;
}
// 计算从 1 到 n 的整数中数字 i 出现的次数 
int count(int n, int i)
{
	int res = 0, d = dgt(n);
	// 从右到左第 j 位上数字出现的次数 
	for (int j = 1; j <= d; j ++) {
		// l 和 r 是第 j 位左边和右边的整数,dj 是第 j 位数字
		int p = pow(10, j - 1), l = n / p / 10, r = n % p, dj = n / p % 10;
		// 第 j 位左边的整数小于 l 的情况 (第 j 位不为 0)
		if (i) res += l * p;
		// 如果 i = 0,左边高位不能全为 0
		if (!i && l)	res += (l - 1) * p;
		// 第 j 位左边的整数等于 l 的情况
		// i || l 表示左高位不全为 0
		// dj 右边的取值 0 ~ p - 1
		if ((dj > i) && (i || l))	res += p;
		// dj 及其左边的都已经到最大,右边的取值 0 ~ r 
		if ((dj == i) && (i || l))	res += r + 1;
	}
	return res;
}
int main()
{
	int a, b;
	while (cin >> a >> b , a) {
		if (a > b)	swap(a, b);
		for (int i = 0; i <= 9; i ++)
			cout << count(b, i) - count(a - 1, i) << ' ';
		cout << endl;
	}
	return 0;
}

  1. 类比前缀和
    可以求出 0b 中每个数字出现的个数和 0a1 中每个数字出现的个数,所要求的为 count(b,i)count(a1,i)
  2. 分类讨论
    统计所有位于 [0,n] 的整数,且数字 i 出现在某一位上的满足条件的整数个数
    i 表示 0 ~ 9 中的一个数字 ,对于一个给定的整数 n=abcdefg ,如果 id 这一位上,p1000 ,所有位于 [0,n] 且满足 x4=i 的整数 x1x2x3x4x5x6x7 可以分为以下情况:
    x1x2x3<abci0x1x2x3 可取 0 ~ abc1x5x6x7 可取 0 ~ p1 ,共 abcp
    x1x2x3<abci=0x1x2x3 可取 1 ~ abc1 (0000efg 不是满足要求的数) ,x5x6x7 可取 0 ~ p1 ,共 (abc1)p
    x1x2x3=abcx4=i<dx5x6x7 可取 0 ~ p1 ,共 p
    x1x2x3=abcx4=i=dx5x6x7 可取 0 ~ efg ,共 efg+1

使用 vector 的写法


点击查看代码
#include<iostream>
#include<vector>

using namespace std;

int get(vector<int> num, int l, int r)
{
	int res = 0;
	for (int i = l; i >= r; i --)	res = res * 10 + num[i];
	return res;
}
int power10(int x)
{
	int res = 1;
	while (x --)	res *= 10;
	return res;	
}
int count(int n, int x)
{
	if (!n)	return 0;
	vector<int> num;
	while (n) {
		num.push_back(n % 10);
		n /= 10;
	}
	n = num.size();
	int res = 0;
	for (int i = n - 1 - !x; i >= 0; i --) {
		if (i < n - 1) {
			res += get(num, n - 1, i + 1) * power10(i);
			if (!x)		res -= power10(i);
		}
		if (num[i] == x)	res += get(num, i - 1, 0) + 1;
		else if (num[i] > x)	res += power10(i);
	}
	return res;
}
int main()
{
	int a, b;
	while (cin >> a >> b, a) {
		if (a > b)	swap(a, b);
		for (int i = 0; i <= 9; i ++)
			cout << count(b, i) - count(a - 1, i) << ' ';
		cout << endl;
	}
	return 0;
}
posted @   wKingYu  阅读(18)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
欢迎阅读『[AcWing 338] 计数问题』
点击右上角即可分享
微信分享提示