可以使用数位 DP 的思想来解决这个问题。
首先,我们可以先把 a 和 b 分别转化为字符串,然后在每一位上统计 0~9 的出现次数。这个可以用一个数组 cnt 来表示,其中 cnt[i][j] 表示第 i 位上数字 j 出现的次数。
接下来,我们需要进行动态规划。我们设 dp[i][j][k] 表示前 i 位数字中数字 j 出现了 k 次的方案数。那么我们可以列出如下转移方程:
dp[i][j][k] = dp[i-1][j][k-cnt[i][j]] + dp[i][j-1][k] ,其中 cnt[i][j] 表示第 i 位上数字 j 出现的次数,即 cnt[i][j] = cnt[i-1][j]+(j==当前位的数字)。
其中,第一项表示第 i 位上数字 j 出现了 cnt[i][j] 次,那么前 i-1 位上数字 j 出现的次数就要减去 cnt[i][j];第二项表示前 i 位上数字 j 出现了 k 次,那么第 i 位上只需要再出现一次即可。
最终答案就是 sum{dp[len][j][k]},其中 len 是 b 的位数,j 是 0~9 中的一个数字,k 是 0~b 的位数之和。
#include
#include
using namespace std;
int digitCount(int n, int digit) // 求数字 digit 在 n 中出现的次数
{
int count = 0;
while (n)
{
if (n % 10 == digit)
{
count++;
}
n /= 10;
}
return count;
}
int main()
{
int a, b;
cin >> a >> b;
int count[10]; // 存储数字 0~9 出现的次数
memset(count, 0, sizeof(count)); // 初始化 count 数组为 0
for (int i = a; i <= b; i++)
{
for (int j = 0; j <= 9; j++)
{
count[j] += digitCount(i, j); // 统计数字 j 在 i 中出现的次数
}
}
for (int i = 0; i <= 9; i++)
{
cout << count[i] << " ";
}
cout << endl;
return 0;
}
但是如果a和b相差太大,比如在一亿的话就会超时,因为c++一秒的计算量在10^7~10^8;
所以如果遇到数据很大的时候,不能够全部枚举,要分情况枚举
#include
#include
using namespace std;
int cnt[10];
void count(int x){
while(x){
cnt[x%10]++;
x /= 10;
}
}
int main(){
int a, b;
cin >> a >> b;
for(int i=a;i<=b;i++){
count(i);
}
for(int i=0;i<=9;i++){
cout << cnt[i] << endl;
}
return 0;
}
思路:
首先定义一个cnt数组,用来记录0~9出现的次数。
然后定义一个count函数,用来计算一个整数中0~9出现的次数。count函数通过不断求模和除以10的操作,统计出当前整数的个位、十位、百位、千位……分别为0~9的出现次数。
最后,根据输入的a、b范围,调用count函数计算出a~b之间所有数字的0~9出现次数,并输出结果。
需要注意的是,由于数据范围在一亿之间,直接使用一个数组来记录每个数字中0~9的出现次数是不现实的,会导致空间爆炸。因此,可以采用边计算边输出的方式,避免使用大量的内存。
如果有多组测试数据
具体代码如下
#include
#include
#include
using namespace std;
const int N = 10;
/*
001~abc-1, 999
abc
1. num[i] < x, 0
2. num[i] == x, 0~efg
3. num[i] > x, 0~999
*/
int get(vector 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 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;
}