我的意思是,对于支点之前的位置,必须有一个有效数位(就不能全都是 0)。这个东西考虑了反而是错误的,为什么?
AC:
long long l, r;
int d[20], top; // d 表示每个数位,top 表示是为长度
long long f[21][21][5001][2][2]; // dp
// f[pos][zd][sum][limited][zero]:
// pos:当前的数位
// zd:支点
// sum:力矩和
// limited:放满没有,放满就是 0,没有就是 1
// zero:之前有没有非零数字
long long solve(int pos, int zd, int sum, int limited, int zero) {
if (pos == top + 1) return sum == 0;
if (f[pos][zd][sum + 2000][limited][zero] != -1) return f[pos][zd][sum + 2000][limited][zero];
long long ans = 0;
for (int i = 0; i <= max(limited * 9, d[pos]); ++i) { // 这里从零开始
ans += solve(pos + 1, zd, sum + (pos - zd) * i, limited || (i != d[pos]), zero || (i != 0));
}
return f[pos][zd][sum + 2000][limited][zero] = ans;
}
WA:
long long solve(int pos, int zd, int sum, int limited, int zero) {
if (pos == top + 1) return sum == 0;
if (f[pos][zd][sum + 2000][limited][zero] != -1) return f[pos][zd][sum + 2000][limited][zero];
long long ans = 0;
for (int i = max(0, (int)(!zero && pos == zd)); i <= max(limited * 9, d[pos]); ++i) { // 如果之前都是零且目前这一位是支点,从 1 开始。
ans += solve(pos + 1, zd, sum + (pos - zd) * i, limited || (i != d[pos]), zero || (i != 0));
}
return f[pos][zd][sum + 2000][limited][zero] = ans;
}
刚学数位 DP,不太理解。