首页 > 代码库 > UVA 11361 - Investigating Div-Sum Property(数位DP)

UVA 11361 - Investigating Div-Sum Property(数位DP)

题目链接:11361 - Investigating Div-Sum Property

白书上的例题,不过没有代码,正好前几天写了一题数位DP的题目,这题也就相对轻松了。
dp[i][x][y]表示加到第i位,数字 % k,数位和 % k的组合情况数,那么现在要添加一个0 - 9的数字上去状态转移为
dp[i + 1][(x * 10 + num) % k][(y + num) % k],计算总和后,由于数字本身不能超过最大值,所以最后还要添加上恰好前几位都为最大值的情况。然后最后在判断一下该数字本身符不符合条件。 注意边界0的时候答案为1.
代码:
#include <stdio.h>
#include <string.h>

int t, a, b, k, f[15][105][105], n, d[15];

void tra(int num) {
	n = 0;
	while (num) {
		d[++n] = num % 10;
		num /= 10;
	}
	for (int i = 1; i <= n / 2; i++) {
		int t = d[i];
		d[i] = d[n + 1 - i];
		d[n + 1 - i] = t;
	}
}

int solve(int num) {
	if (num == 0) return 1;
	tra(num);
	memset(f, 0, sizeof(f));
	int x1 = 0, x2 = 0;
	for (int i = 1; i <= n; i++) {
		for (int x = 0; x < k; x++) {
			for (int y = 0; y < k; y++) {
				for (int j = 0; j <= 9; j++) {
					f[i][(x * 10 + j) % k][(y + j) % k] += f[i - 1][x][y];
				}
			}
		}
		for (int j = 0; j < d[i]; j++)
			f[i][(x1 * 10 + j) % k][(x2 + j) % k]++;
		x1 = (x1 * 10 + d[i]) % k;
		x2 = (x2 + d[i]) % k;
	}
	if (x1 == 0 && x2 == 0)
		f[n][0][0]++;
	return f[n][0][0];
}

int main() {
	scanf("%d", &t);
	while (t--) {
		scanf("%d%d%d", &a, &b, &k);
		if (k > 100) printf("0\n");
		else printf("%d\n", solve(b) - solve(a - 1));
	}
	return 0;
}