力扣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;
}

浙公网安备 33010602011771号