Lilliput Steps

小さな一歩から着実に. 数学やプログラミングのことを書きます.

Typical DP Contest E - 数

問題文 :


解法 :
$dp[i][j] :=$ 桁$i$ までの和 mod $D$ が$j$ になるものの総数, としてDP. ここで, DP をしている時の数字が上限$L$ に引っかかっていないかを状態として持つと楽.

コード :

#include <cstdio>
#include <cstring>

using namespace std;

int MOD = 1000000007;

char P[10001];
int dp[10001][100][2];
int L, D;

int count(int pos, int mod, bool free)
{
	if (pos == L) return (mod == 0);
	if (dp[pos][mod][free] >= 0) return (dp[pos][mod][free]);
	
	int ret = 0;
	for (int i = 0; i <= (free ? 9 : P[pos] - '0'); i++){
		ret = (ret + count(pos + 1, (mod + i) % D, free | (i < P[pos] - '0'))) % MOD;
	}
	
	return (dp[pos][mod][free] = ret);
}

int main()
{
	memset(dp, -1, sizeof(dp));
	scanf("%d", &D);
	scanf("%s", P);
	
	L = strlen(P);
	
	printf("%d\n", (count(0, 0, 0) + MOD - 1) % MOD);
}