2019-2020 ICPC Asia Hong Kong Regional Contest J—Junior Mathematician 数位dp

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod = 1e9 + 7;
const int N = 5010;
char str1[N], str2[N];
int p[N], a[N], mod2;
ll dp[N][65][65];
ll dfs(int pos, int sum, int last, bool limit)
{
	if (pos < 1)
		return !last;
	if (!limit && dp[pos][sum][last] != -1)
		return dp[pos][sum][last];
	ll ans = 0;
	int up = (limit ? a[pos] : 9);
	for (int i = 0; i <= up; i++)
		ans += dfs(pos - 1, (sum + i) % mod2, ((last + i * sum - i * p[pos - 1]) % mod2 + mod2) % mod2,i == up && limit);
	ans %= mod;
	if (!limit)
		dp[pos][sum][last] = ans;
	return ans;
}
ll solve(char s[])
{
	int len = strlen(s + 1);
	for (int i = 1; i <= len; i++)
		for (int j = 0; j <= mod2; j++)
			for (int k = 0; k <= mod2; k++)
				dp[i][j][k] = -1;
	for (int i = 1; i <= len; i++)
		a[i] = s[len - i + 1] - '0';
	return dfs(len, 0, 0, true);
}
int main()
{

	p[0] = 1;
	int T;
	scanf("%d",&T);
	while (T--)
	{
		scanf("%s",str1 + 1);
		getchar();
		scanf("%s",str2 + 1);
		getchar();
		scanf("%d",&mod2);
		int n = strlen(str2 + 1);
		int m = strlen(str1 + 1);
		for (int i = 1; i <= n; i++)
			p[i] = p[i - 1] * 10 % mod2;
		//处理好前缀和的形式,不然下一步忒麻烦了。
		str1[m]--;
		for (int i = m; i >= 1; i--)
		{
			//特判,借位
			if (str1[i] - '0' < 0)
				str1[i] += 10, str1[i - 1]--;
			else
				break;
		}
		ll ans= (solve(str2) - solve(str1) + mod) % mod;
		printf("%lld
",ans);
	}

	return 0;
}
原文地址:https://www.cnblogs.com/QingyuYYYYY/p/12818233.html