ACWING311. 月之谜(数位DP)

无人久伴 提交于 2020-01-21 12:30:51

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

给定整数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;
}

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!