hdu2089 不要62(数位dp入门题)
题目链接: hdu2089 ( 不要62 )
\(dp[i][j]\) 代表 \(i\) 位数首位为 \(j\) 的吉利数字个数。
则有
\[dp[i][j] =
\begin{cases}0&,j=4\\
\sum_{k=0}^9 (j\ne 6 \or k\ne 2)dp[i-1][k]&,j\ne 4\end{cases}
\]
求 \([0,n)\) 内吉利数个数时要求
- 从高位往低位遍历
- 遍历完当前位后,若高几位出现 \(4\) 或 \(62\) 则停止向低位遍历,跳出循环。
\(AC\) 代码:
/**
* hdu2089 不要62
* 数位dp
*/
#include <iostream>
#include <climits>
#include <cmath>
#include <iomanip>
#include <vector>
#include <cstring>
using namespace std;
typedef long long LL;
const int N = 8;
int dp[N][10]; // dp[i][j]代表i位数首位为j时的吉利数字个数
void init()
{
dp[0][0] = 1;
for (int i = 1; i < N; ++i) {
for (int j = 0; j < 10; ++j) {
if (j != 4)
for (int k = 0; k < 10; ++k) {
if(j == 6 && k == 2) continue;
dp[i][j] += dp[i-1][k];
}
// cout << setw(7) << dp[i][j] << ' ';
}
// cout << endl;
}
}
int digit[N];
int solve(int n) // 求解[0,n)区间内满足条件数字个数
{
int len = 0;
while (n) {
digit[++len] = n % 10;
n /= 10;
}
digit[len+1] = 0;
int res = 0;
for (int i = len; i > 0; --i) {
for (int j = 0; j < digit[i]; ++j) {
if (j == 2 && digit[i+1] == 6) continue;
res += dp[i][j];
}
if (digit[i] == 4 || digit[i] == 2 && digit[i+1] == 6) break;
}
return res;
}
int main()
{
init();
int n, m;
while (cin >> n >> m && (n|m)) {
cout << solve(m+1) - solve(n) << endl;
}
return 0;
}