一本通1588:数字游戏
数位dp
挺裸的一个板子,具体看代码吧(有注释)
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
int l, r, mod, len;
int num[13], dp[13][110][2][2]; //dp[len][sum][flag][lim]记忆化,含义见下
int dfs(int len, int sum, int flag, int lim){ //len:倒着处理到第len位,sum:已处理的各位数字之和,flag:前面是否为前导0(1:是 0:否),lim:是否有上限(1:是 0:否)
if(!len) return (dp[len][sum][flag][lim] = (sum % mod == 0) ? 1 : 0); //处理完所有数位,返回
if(dp[len][sum][flag][lim] != -1) return dp[len][sum][flag][lim]; //记忆化
int res = lim ? num[len] : 9;
int ans = 0;
for(int i = 0; i <= res; i++)
ans += dfs(len - 1, sum + i, flag && (!i), lim && (i == res)); //flag,lim传递手玩一下就好
return dp[len][sum][flag][lim] = ans; //还是记忆化
}
int solve(int x){
if(!x) return 1; //0 % mod == 0
len = 0;
while(x){
num[++len] = x % 10; //这里num是倒着存的x的各个数位
x /= 10;
}
int ans = 0;
memset(dp, -1, sizeof(dp)); //注意dp数组初值赋成-1
return dfs(len, 0, 1, 1);
}
int main(){
while(scanf("%d%d%d", &l, &r, &mod) != EOF)
printf("%d
", solve(r) - solve(l - 1));
return 0;
}
完结撒花~