Typical DP Contest E: 数 (動的計画法)
解法
下からi桁目まで見た時にj余る整数の数を記録しておく。この時、i桁目がNのi桁目以下になる数も記録しておく。
コード
import java.util.Scanner; public class Main { private static final long MOD = 1000000007; public static void main(String[] args) { Scanner sc = new Scanner(System.in); int D = sc.nextInt(); char[] input = sc.next().toCharArray(); sc.close(); int N = input.length;// 桁数 int[] nums = new int[N]; for (int i = 0; i < nums.length; i++) { nums[i] = Character.getNumericValue(input[i]); } // dp[i][j]:= i+1桁目まで見てj余る整数の数 long[][] dp = new long[N + 1][D]; long[][] dpLarger = new long[N + 1][D];// N桁の99999...の中のDの倍数を記録する dp[N][0] = 1; dpLarger[N][0] = 1; for (int n = N - 1; n >= 0; n--) { for (int d = 0; d < D; d++) { for (int j = 0; j <= 9; j++) { int rest = d - j; rest = (rest + 10 * D) % D; dpLarger[n][d] += dpLarger[n + 1][rest]; dpLarger[n][d] %= MOD; } for (int j = 0; j < nums[n]; j++) { int rest = d - j; rest = (rest + 10 * D) % D; dp[n][d] += dpLarger[n + 1][rest]; dp[n][d] %= MOD; } int rest = d - nums[n]; rest = (rest + 10 * D) % D; dp[n][d] += dp[n + 1][rest]; dp[n][d] %= MOD; } } // 000...を含まないようにする System.out.println(dp[0][0] - 1); } }