数位dp
状态可表示为f(位数,最高位,最长相同数字前缀长度(大于3取3),是否有连续三位相同,是否出现4,是否出现8)共6维
#include<cstdio> typedef long long lint; lint f[15][10][3][2][2][2]; lint L,R; int stk[16],p=0; lint calc(lint x){ p=0; lint ans=0,x0=x; while(x)stk[++p]=x%10,x/=10; for(int i=1;i<p;i++){ for(int j=1;j<10;j++){ for(int a=0;a<3;a++) ans+=f[i][j][a][1][0][0]+f[i][j][a][1][0][1]+f[i][j][a][1][1][0]; } } for(int i=1;i<stk[p];i++){ for(int a=0;a<3;a++) ans+=f[p][i][a][1][0][0]+f[p][i][a][1][0][1]+f[p][i][a][1][1][0]; } int p1=stk[p],p2=0; int d4=p1==4,d8=p1==8,l3=0; for(int i=p-1;i;--i){ for(int j=0;j<stk[i];j++){ for(int a=0;a<3;a++){ ans+=f[i][j][a][1][0][0]; if(!d4)ans+=f[i][j][a][1][0][1]; if(!d8)ans+=f[i][j][a][1][1][0]; if(l3){ ans+=f[i][j][a][0][0][0]; if(!d4)ans+=f[i][j][a][0][0][1]; if(!d8)ans+=f[i][j][a][0][1][0]; } } if(l3)continue; if(p1==j){ ans+=f[i][j][1][0][0][0]; if(!d4)ans+=f[i][j][1][0][0][1]; if(!d8)ans+=f[i][j][1][0][1][0]; if(p1==p2){ ans+=f[i][j][0][0][0][0]; if(!d4)ans+=f[i][j][0][0][0][1]; if(!d8)ans+=f[i][j][0][0][1][0]; } } } if(p1==p2&&p1==stk[i])l3=1; p2=p1;p1=stk[i]; if(p1==4){ if(d8)break; d4=1; } if(p1==8){ if(d4)break; d8=1; } } return ans; } int main(){ for(int i=0;i<10;i++)f[1][i][0][0][i==4][i==8]=1; for(int i=2;i<=12;i++){ for(int j=0;j<10;j++){ for(int k=0;k<10;k++){ for(int d4=0;d4<2;d4++){ for(int d8=0;d8<2;d8++){ if(j!=k){ for(int w=0;w<3;w++) f[i][j][0][0][d4||j==4][d8||j==8]+=f[i-1][k][w][0][d4][d8], f[i][j][0][1][d4||j==4][d8||j==8]+=f[i-1][k][w][1][d4][d8]; }else{ f[i][j][1][0][d4||j==4][d8||j==8]+=f[i-1][k][0][0][d4][d8]; f[i][j][1][1][d4||j==4][d8||j==8]+=f[i-1][k][0][1][d4][d8]; f[i][j][2][1][d4||j==4][d8||j==8]+=f[i-1][k][1][0][d4][d8]; f[i][j][2][1][d4||j==4][d8||j==8]+=f[i-1][k][1][1][d4][d8]; f[i][j][2][1][d4||j==4][d8||j==8]+=f[i-1][k][2][1][d4][d8]; } } } } } } scanf("%lld%lld",&L,&R); printf("%lld",calc(R+1)-calc(L)); return 0; }