题目链接:点击打开链接
题目大意:在给定的n和m之间 不含4和62(连续)的数目
题目分析:打表应该可以过,毕竟只有10^7,但是一旦大的惊人就无法保证了
参考资料:点击打开链接
需要统计区间【l , r】 可以 换成【0,r】-【0,L)!
用数组 f [ i ] [ j ] 来对数进行预处理 i表示第i位,j 表示 状态 j。
f[ i ][ j ]= f[ i-1 ][ k ]+f [ i ][ j ];
然后根据mn 的具体大小,将m,n的每一位一次放入digit【i】中;
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
int digit[15],f[15][15];
void init()
{ memset(f,0,sizeof(f));
f[0][0]=1;//注意!!f【0】【0】
for(int i=1;i<=8;i++)//枚举位数
{
for(int j=0;j<=9;j++)//第i位,枚举0~9
{
for(int k=0;k<=9;k++)//枚举i-1位
{
if(j!=4&&(j!=6||k!=2))//如果是文中叙述的情况;
f[i][j]+=f[i-1][k];
}
}
}
}
int divid(int x)
{
int i=1;
memset(digit,0,sizeof(digit));
while(x)
{
digit[i++]=x%10;
x/=10;
} return i;
}
int main()
{
int n,m,i,j,k,ans;
init();
while((scanf("%d%d",&n,&m)!= EOF)&&(n||m))
{
ans=0;m=divid(m)-1;
for(i=m;i>=1;i--)
{
for(j=0;j<digit[i];j++)
{
if(j!=4&&(j!=2||digit[i+1]!=6))
ans+=f[i][j];
}if(digit[i]==4||(digit[i]==2&&digit[i+1]==6))
{ans--;break;}//已经出现了,所以往后走必然带62或者4
}m=ans;ans=0;
n=divid(n-1)-1;//注意开区间
for(i=n;i>=1;i--)
{
for(j=0;j<digit[i];j++)
{
if(j!=4&&(j!=2||digit[i+1]!=6))
{ans+=f[i][j];}
}
if(digit[i]==4||(digit[i]==2&&digit[i+1]==6)) {ans--;break;}
}
printf("%d\n",m-ans);
}
return 0;
}