记录状态,pos当前位置,pre前一个数,ppre前前一个数,f是否有连续三个相等,f4是否出现4,f8是否出现8。
记忆化这些变量,保证状态不冲突,对于长度,因为固定了11位,所以不用记录了。
还有就是很坑的就是,虽然题目范围保证了数据都是11位,但如果当
,l-1就只有10位了,所以必须得特判。
code
#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
const int man = 2e5+10;
#define IOS ios::sync_with_stdio(0)
#define ull unsigned ll
#define uint unsigned
#define pai pair<int,int>
#define pal pair<ll,ll>
#define IT iterator
#define pb push_back
#define fi first
#define se second
#define For(i,j,k) for (int i=(int)(j);i<=(int)(k);++i)
#define Rep(i,j,k) for (int i=(int)(j);i>=(int)(k);--i)
#define endl '\n'
#define ll long long
const ll mod = 1e9+7;
int str[15];
ll dp[13][10][10][2][2][2];
ll dfs(int pos,int pre,int ppre,bool f,bool f4,bool f8,bool limit){
if(f4&&f8)return 0;//剪枝,很明显没必要搜索下去了
if(!pos){
return f;
}
ll &x = dp[pos][ppre][pre][f][f4][f8];
if(!limit&&x!=-1)return x;
int up = limit?str[pos]:9;
ll ans = 0;
for(int i = 0;i <= up;++i){
bool tpf = f||((pre==ppre)&&(pre==i));
bool tpf4 = f4||(i==4);
bool tpf8 = f8||(i==8);
ans += dfs(pos-1,i,pre,tpf,tpf4,tpf8,limit&&i==up);
}
if(!limit)x = ans;
return ans;
}
ll slove(ll x){
int len = 0;
while(x){
str[++len] = x % 10;
x/=10;
}
if(len!=11)return 0;
ll res = 0;
int up = str[len];
for(int i =1;i<= up;i++){
// cout << "iL:" << i << endl;
res += dfs(len-1,i,0,0,(i==4),(i==8),(i==up));
}
return res;
}
signed main() {
#ifndef ONLINE_JUDGE
//freopen("in.txt", "r", stdin);
// freopen("out.txt","w",stdout);
#endif
memset(dp,-1,sizeof(dp));
ll l,r;
scanf("%lld%lld",&l,&r);
printf("%lld\n",slove(r)-slove(l-1));
return 0;
}