Counting Numbers
Complejidad temporal:
Usaremos DP de dígitos para resolver este problema.
Primero, en lugar de hallar la respuesta para el rango , hallamos las respuestas para los rangos y , y su diferencia será la respuesta. (Se verá que se usa esta técnica en casi todos los problemas de DP de dígitos).
Sea la cantidad de enteros buenos con dígitos y cuyo -ésimo dígito es . La recurrencia es y los casos base son para cada . Calcular la DP a mano muestra que .
¿Cómo contamos la cantidad de enteros buenos no mayores que un dado con dígitos? Tenemos dos casos:
- El entero bueno tiene dígitos.
- El entero bueno tiene dígitos.
Cualquier entero bueno que caiga en el primer caso se cuenta en la respuesta, así que este caso contribuye exactamente a la respuesta.
El segundo caso es un poco más tramposo. La observación clave es que cualquier bueno no mayor que que caiga en este caso satisface dos condiciones:
- e comparten un prefijo común de longitud sin dígitos vecinos iguales.
- El -ésimo dígito de es menor que el -ésimo dígito de .
Esto significa que, para cada prefijo fijo (bueno) de los dígitos de , podemos contar la cantidad de buenos con ese prefijo. Si el -ésimo dígito de es , entonces contribuye a la respuesta. Si , entonces también debemos restar de la respuesta para evitar que dos dígitos consecutivos sean iguales.
Como podemos procesar cada dígito de y en tiempo , esta solución funciona en tiempo .
#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
ll pow_9[19]{1};
ll calc(ll x) {
if (x == -1) return 0;
ll ans = 0;
vector<int> digits;
while (x) {
digits.push_back(x % 10);
x /= 10;
}
for (int i = 0; i < (int)digits.size() - 1; i++) ans += pow_9[i];
digits.push_back(10);
for (int i = (int)digits.size() - 2; ~i; i--) {
ans += digits[i] * pow_9[i];
if (digits[i] > digits[i + 1]) ans -= pow_9[i];
if (digits[i] == digits[i + 1]) return ans;
}
return ans + 1;
}
int main() {
cin.tie(0)->sync_with_stdio(0);
for (int i = 1; i <= 18; i++) pow_9[i] = 9 * pow_9[i - 1];
ll a, b;
cin >> a >> b;
cout << calc(b) - calc(a - 1);
return 0;
}