题目大意
人们将含有62和4的数成为不吉利的数字,大家都不喜欢不吉利的数字。 现给出两个整数n和m,求出从n到m的数字中有多少吉利的数字(不含有62或4的数字)。
解题思路
又是一个数位DP的典型题目,与我之前写过的(HDU 3555 Bomb)相比增加了一点点的难度,判断中需要仔细一点,思路还是相同的。
设立一个二维数组dp[i][j],保存当数字为i位长的时候的情况,j=0表示不含有62且不含有4且不以2开头的数,j=1代表不含有62且不含有4但以2开头的数字的个数,j=2代表含有62或4的数(不吉利的数字)的个数。
转移方程:
dp[i][0]=9*dp[i-1][0]-dp[i-1][1];
//在i-1位数的基础上构造i位数时,首位可以添加处4以外的数字,还要减去添加的数位6且原首位为2的情况。
dp[i][1]=dp[i-1][0];
//在原基础上首位添加数字为2,已经包含了原来首位为2的情况,所以不需要另外考虑。
dp[i][2]=10*dp[i-1][2]+dp[i-1][1]+dp[i-1][0];
//原有的62增加任意首位+原有首位为2添加6构成62+原有任意首位添加4的情况。
附上代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int dp[
100][
3],n,m,num[
20];
void init()
{
memset(dp,
0,
sizeof(dp));
dp[
0][
0]=
1;
for(
int i=
1;i<=
10;i++){
dp[i][
0]=
9*dp[i-
1][
0]-dp[i-
1][
1];
dp[i][
1]=dp[i-
1][
0];
dp[i][
2]=
10*dp[i-
1][
2]+dp[i-
1][
1]+dp[i-
1][
0];
}
}
int solve(
int k)
{
memset(num,
0,
sizeof(num));
int ans=
0,cont=
0,temp=k;
while(k){
num[++cont]=k%
10;
k/=
10;
}
bool flag=
false;
for(
int i=cont;i>=
1;i--){
ans+=num[i]*dp[i-
1][
2];
if(flag)
ans+=dp[i-
1][
0]*num[i];
else{
if(num[i]>
4)
ans+=dp[i-
1][
0];
if(num[i+
1]==
6&&num[i]>
2)
ans+=dp[i][
1];
if(num[i]>
6)
ans+=dp[i-
1][
1];
}
if(num[i]==
4||(num[i+
1]==
6&&num[i]==
2))
flag=
true;
}
return temp-ans;
}
int main()
{
int ans1,ans2,ans;
init();
while(~
scanf(
"%d%d",&n,&m),n+m)
{
ans1=solve(n);
ans2=solve(m+
1);
ans=ans2-ans1;
printf(
"%d\n",ans);
}
return 0;
}
转载请注明原文地址: https://ju.6miu.com/read-8180.html