力扣3490 统计美丽整数的数目

题目要求区间 \([l,r]\) 内各位数字之和与各位数字之积相等的整数个数,不难想到数位 dp。因为没有注意到 \(9\)\(0-9\) 整数的乘积状态数只有 \(3000\) 左右,试图用【AHOI2009 同类分布】的做法。原题是求出 \([l.r]\) 中各位数字之和等于原数的个数,做法是枚举原数除以 \(sum\) 的余数 \(m\)\(9\)\(0-9\) 数字共 \(81\) 种状态),如果最后 \(sum=m, num\equiv 0 \pmod{m}\)

对于本题,状态转移的 \(num\times 10+i\) 要改成 \(num\times i\)。因为数字可能有前导零,导致乘积为 0,所以需要多开一维 \(0/1\) 判断是否为前导零。如果是则保持 \(num=1\)

int a[20] = {0}, mod;
int f[20][100][100];

int dfs(int len, int lim, int sum, int num, bool zero) {
    if (len == 0) {
        if (sum == 0) return 0;
        return sum == mod && num == 0;
    }
    if (!lim && !zero && f[len][sum][num] != -1)
        return f[len][sum][num];
    int up = lim ? a[len] : 9;
    int ans = 0;
    for (int i = 0; i <= up; ++i) {
        int t = zero && (!i);
        ans += dfs(len - 1, lim && i == up, sum + i, (t ? 1 : num * i % mod), t);
    }
    if (!lim && !zero) f[len][sum][num] = ans;
    return ans;
}

int calc(int x) {
    int len = 0;
    while (x) {
        a[++len] = x % 10;
        x /= 10;
    }
    int ans = 0;
    for (mod = 1; mod <= len * 9; ++mod) {
        memset(f, -1, sizeof f);
        ans += dfs(len, 1, 0, 1, 1);
    }
    return ans;
}
posted @ 2025-03-16 17:23  XYukari  阅读(32)  评论(0)    收藏  举报