c++计数统计

可以使用数位 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;
}

你可能感兴趣的:(c++,算法,动态规划)