题解
①L~R的符合要求的数字个数,我们可以转化为1~R的符合要求的数字个数 减去 1~(L-1)的美丽数字个数
②定义dp[pos]为选前pos位的方案数。由于要一位一位的去选,dp方程不太好写,所以选择写记忆化搜索。首先需要记录pos(选到了第几位),pre(上一位选的数字),limit(之前的位是否都选到了上限值)。比如327,如果前两位选了32,那么第三位就只能选1~7,如果第一位没选3或第二位没选2,那么第三位就可以选0~9。
那么有哪些状态是重复的需要记忆化呢,不难想到就是dp[pos位(每一位0~9随便选)]。
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1000005;
int dp[10];
string num;
int dfs(int pos, int pre, bool limit)
{
if (pos == -1) return 1;
if (!limit && pre != 6 && dp[pos] != -1) return dp[pos];
int E = limit?num[pos]-'0':9, ans = 0;
for (int i = 0; i <= E; i++)
{
if (i == 4 || pre == 6 && i == 2) continue;
ans += dfs(pos-1, i, limit&&i == E);
}
if (!limit && pre != 6) dp[pos] = ans;
return ans;
}
int solve(int x)
{
num = to_string(x); reverse(num.begin(), num.end());
return dfs(num.size()-1, 0, 1);
}
int main()
{
memset(dp, -1, sizeof(dp));
int L, R;
while (~scanf("%d%d", &L, &R) && (L+R))
{
printf("%d\n", solve(R) - solve(L-1));
}
return 0;
}
/*
1 100
0 0
*/