bzoj 4521: [Cqoi2016]手机号码【数位dp】
比较基础的数位dp,dfs的时候带上上一位,上上位,是否已经有连续3个相同位,是否有4,是否有8即可
但是要注意两点(在洛谷上一直70)
当l=1e10的时候,直接输出clc(r)即可,因为如果再减去clc(l-1)的话,是会多减掉1的
还有判断前导0
#include<iostream>
#include<cstdio>
using namespace std;
const int N=15;
long long l,r,f[N][N][N][2][2][2],a[N],tot;
long long dfs(int w,int laa,int la,bool ok,bool si,bool ba,bool lm)
{
if(si&&ba)
return 0;
if(!w)
return ok;
if(!lm&&f[w][laa][la][ok][si][ba])
return f[w][laa][la][ok][si][ba];
long long r=0;
for(int i=0;i<=(lm?a[w]:9);i++)
r+=dfs(w-1,la,i,(ok|(laa==la&&la==i)),(si|(i==4)),(ba|(i==8)),lm&&i==a[w]);
if(!lm)
f[w][laa][la][ok][si][ba]=r;
return r;
}
long long clc(long long x)
{
tot=0;
while(x)
a[++tot]=x%10,x/=10;
long long r=0;
for(int i=1;i<=a[tot];i++)
r+=dfs(tot-1,-1,i,0,i==4,i==8,i==a[tot]);
return r;
}
int main()
{
scanf("%lld%lld",&l,&r);
if(l==10000000000)
printf("%lld\n",clc(r));
else
printf("%lld\n",clc(r)-clc(l-1));
return 0;
}