ACWING311. 月之谜(数位DP)

如果一个十进制数能够被它的各位数字之和整除,则称这个数为“月之数”。

给定整数L和R,你需要计算闭区间[L,R]中有多少个“月之数”。

输入格式
输入占一行,包含两个整数L和R。

输出格式
输出一个整数,表示月之数的个数。

数据范围
1≤L,R<231
输入样例:
1 100
输出样例:
33

思路:
如果记录的是数字大小和数字位总和,最后再来比较,那么就不能实现记忆化(相当于每个数字都判断一遍)

实际的数字位和不大,可以枚举这个数字位和。

#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

int MOD;
int digit[20];
int dp[12][205][205];
int dfs(int len,int mod,int sum,int limit)
{
    if(len == 0)
    {
        if(mod == 0 && sum == MOD)return 1;
        else return 0;
    }
    if(!limit && dp[len][mod][sum] != -1)return dp[len][mod][sum];
    int up = limit ? digit[len] : 9;
    int ans = 0;
    for(int i = 0;i <= up;i++)
    {
        ans += dfs(len - 1,(mod * 10 + i) % MOD,sum + i,i == up && limit);
    }
    return limit ? ans : dp[len][mod][sum] = ans;
}

int solve(int x)
{
    int cnt = 0;
    while(x)
    {
        digit[++cnt] = x % 10;
        x /= 10;
    }
    int ans = 0;
    for(MOD = 1;MOD <= 200;MOD++)
    {
        memset(dp,-1,sizeof(dp));
        ans += dfs(cnt,0,0,1);
    }
    return ans;
}

int main()
{
    memset(dp,-1,sizeof(dp));
    int l,r;scanf("%d%d",&l,&r);
    printf("%d\n",solve(r) - solve(l - 1));
    return 0;
}

发布了628 篇原创文章 · 获赞 17 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/tomjobs/article/details/104057599