【Luogu P4127】[AHOI2009]同类分布
题目大意:
给出两个数 \(a,b\),求出 \([a,b]\) 中各位数字之和能整除原数的数的个数。
正文:
在区间内的计数内问题,考虑到使用 数位DP。
抓住题目大意中的关键词:
求出 \([a,b]\) 中各位数字之和能整除原数的数的个数。
一般数位DP的状态的隐藏在题目中,因此得出动态规划的状态 \(f_{len,sum,mod,pos}\) 表示当第 \(len\) 位各位数字之和为 \(sum\) 除原数的余是 \(mod\) 且有没有碰顶时的个数。得到了状态接下来就只是简单的板子了。
代码:
ll dfs(ll len, ll sum, ll x, bool pos)
{
if(sum + 9 * len < mod) return 0;
if(!len) return sum == mod && x == 0;
if((~f[len][sum][x][pos])&& !pos)
return f[len][sum][x][pos];
int m = pos ? a[len]: 9;
ll ans = 0;
for (int i = 0; i <= m && i + sum <= mod; i++)
{
ans += dfs(len - 1, sum + i, (10ll * x + i) % mod, i == a[len] && pos);
}
if(!pos) f[len][sum][x][pos] = ans;
return ans;
}
ll solve(ll n)
{
memset(a, 0, sizeof(a));
ll x = n;
ll len = 0;
for (; x; x /= 10)a[++len] = x % 10;
ll ans = 0;
for (mod = 1; mod <= len * 9; mod ++)
{
memset(f, -1, sizeof(f));
ans += dfs(len, 0, 0, 1);
}
return ans;
}