做法:基本数位DP了,写情况的时候小心点啊。本来想用自动机的,可是....不行啊,重叠状况难以去掉,而且下面的source简直是...
#include <iostream>
#include <cstdio>
//注意多余0的情况
const int LMT=9;
using namespace std;
int dp[LMT][10],re[LMT][10],num[LMT];
void init(void)
{
for(int i=0;i<=9;i++)
if(i!=4)dp[1][i]=re[1][i]=1;
for(int i=2;i<LMT;i++)
for(int j=0;j<=9;j++)
if(j!=4)
{
for(int t=0;t<=9;t++)
if(t!=4&&(j!=2||t!=6))
{
dp[i][j]+=dp[i-1][t];
if(i==2&&t==0)
dp[i][j]-=dp[i-1][t];
}
}
for(int i=2;i<LMT;i++)
for(int j=0;j<=9;j++)
if(j!=4)
for(int t=0;t<=9;t++)
if(t!=4&&(j!=6||t!=2))
re[i][j]+=re[i-1][t];
}
int leng(int x)
{
int ret=0;
do
num[ret++]=x%10;
while(x/=10);
return ret;
}
int work(int x)
{
int len=leng(x),pos=-1,res=0,end;
for(int i=len-1;i>=0;i--)
if(num[i]==4||(i<len-1&&num[i+1]==6&&num[i]==2))
{
pos=i;break;
}
if(pos==-1)res++;
for(int i=len-1;i>0;i--)
for(int j=0;j<=9;j++)
res+=dp[i][j];
for(int i=len-1;i>=0;i--)
{
if(i>=pos)
{
if(i==len-1&&len>1)end=1;
else end=0;
for(int j=num[i]-1;j>=end;j--)
{
res+=re[i+1][j];//要记得当前的长度啊
if(i<len-1&&num[i+1]==6&&j==2)res-=re[i+1][j];
//这个思考比较复杂,先写下来吧,打草稿,防止出粗,判断小于大于的时候三思啊
}
}
}
return res;
}
int main()
{
int n,m;
init();
while(~scanf("%d%d",&n,&m)&&(m||n))
printf("%d\n",work(m)-work(n-1));
return 0;
}