求助AC了但是没过样例
查看原帖
求助AC了但是没过样例
1214654
LudwigPlanck楼主2025/6/3 23:11

递推数位dp虽然AC了但是没过样例

// LuoGu P2602: [ZJOI2010]数字计数
#include <bits/stdc++.h>
#define endl '\n'
#define int long long
static int dp[15][15][2][2]; // dp[pos][sum][limit][leading_zero] pos: 当前处理的数位位置, sum: 当前数位d出现的次数, limit: 是否限制在前缀上, leading_zero: 是否有前导0
// 计算数字num中数位d出现的个数
int calc(int num, int d)
{
    if (num == 0) if (d == 0) return 1; // 特例处理,0中数位0出现1次
    if (num == 0) return 0; // 如果num为0且d不为0,则返回0
    memset(dp, 0, sizeof(dp)); 
    dp[0][0][1][0] = 1; // 初始化,表示前缀为空时,数位d出现0次
    std::string s = std::to_string(num);
    int n = s.size();
    for (int pos = 0; pos < n; pos++)
    {
        for (int cnt = 0; cnt <= pos; cnt++)
        {
            for (int tight = 0; tight <= 1; tight++)
            {
                for (int leadingZero = 0; leadingZero <= 1; leadingZero++)
                {
                    int up = tight ? s[pos] - '0' : 9;
                    for (int digit = 0; digit <= up; digit++)
                    {
                        int newTight = tight && (digit == up);
                        int newLeadingZero = leadingZero;
                        int newCnt = cnt;
                        if (leadingZero == 0 && digit != 0)
                        {
                            newLeadingZero = 1; // 如果当前数位不是0,则不再是前导0
                        }
                        if (newLeadingZero && digit == d)
                        {
                            newCnt++; // 如果当前数位是d且不是前导0,则计数增加
                        }
                        dp[pos + 1][newCnt][newTight][newLeadingZero] += dp[pos][cnt][tight][leadingZero];
                    }
                }
            }
        }
    }
    int res = 0;
    for (int cnt = 0; cnt <= n; cnt++)
    {
        for (int tight = 0; tight <= 1; tight++)
        {
            for (int leadingZero = 0; leadingZero <= 1; leadingZero++)
            {
                res += dp[n][cnt][tight][leadingZero] * cnt; // 累加所有可能的计数
            }
        }
    }
    return res;
}

void solve()
{
    int a, b;
    std::cin >> a >> b;
    if (a > b) std::swap(a, b);
    std::vector<int> counts(10, 0);
    for (int d = 0; d < 10; d++)
    {
        counts[d] = calc(b, d) - calc(a - 1, d); // 计算在区间[a, b]中数位d出现的次数
    }
    for (int d = 0; d < 10; d++)
    {
        std::cout << counts[d] << (d == 9 ? '\n' : ' '); // 输出每个数位d的出现次数
    }
}

signed main()
{
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr); std::cout.tie(nullptr);
    solve();
    return 0;
}


2025/6/3 23:11
加载中...