那么我们可以设dp[i][j][k=0/1]表示在考虑第i位之前的数位和(模d)等于j,以及是否已经小于上界的方案数。转移也很简单,对于状态dp[i][j][k],只需要枚举第i位的值x[i],那么转移到的状态为dp[i+1][(j+x[i])%d][k or x[i]<r[i]]。最后一个值的意思是,小于上界的条件是之前已经小于上界或者当前位小于上界对应位。
思路已经很清楚了,接下来看一下核心Code:
dp[0][0][0] = 1;
for (int i = 0; i < n; ++i){
for (int j = 0; j < d; ++j){
for (int k = 0; k < 2; ++k){
for (int cur = 0; cur <= 9; ++cur){
if (k == 0 and cur > r[i])
break;
dp[i + 1][(j + cur) % d][k or cur < r[i]] += dp[i][j][k];
}
}
}
}
//小于上界+不小于上界(即等于上界)- 0的情况(因为题目里不包含0
ans = dp[n][0][0] + dp[n][0][1] - 1;