H y p e r l i n k Hyperlink Hyperlink
https://www.luogu.com.cn/problem/P4124
D e s c r i p t i o n Description Description
求出 [ L , R ] [L,R] [L,R]中有多少 x ∈ N + x\in N^+ x∈N+满足 x x x存在三位连续的数字并且不含4和8
数据范围: L , R L,R L,R是11位的正整数
S o l u t i o n Solution Solution
设 f r e s t , l a s t , l l a s t , h f , _ 4 , _ 8 f_{rest,last,llast,hf,\_4,\_8} frest,last,llast,hf,_4,_8表示还剩余 r e s t rest rest位,上一位填的 l a s t last last,上上一位填的 l l a s t llast llast,当前填写的方案是否出现过三个连续数字,是否出现过4,是否出现过8
然后直接套板子,注意 l i m i t = 1 limit=1 limit=1的时候是不能记忆化的,因为可能多算,当然你也可以多开一维保存这种状态,不过在复杂度足够的情况下还是没有必要的
C o d e Code Code
#include<cctype>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long
using namespace std;LL L,R;
int a[15],m;
LL f[12][11][11][2][2][2];
inline LL read()
{
char c;LL d=1,f=0;
while(c=getchar(),!isdigit(c)) if(c=='-') d=-1;f=(f<<3)+(f<<1)+c-48;
while(c=getchar(),isdigit(c)) f=(f<<3)+(f<<1)+c-48;
return d*f;
}
inline LL dfs(int rest,int last,int llast,bool hf,bool _4,bool _8,bool limit)
{
if(_4&&_8) return 0;
if(rest==0) return hf;
if(limit==false&&f[rest][last][llast][hf][_4][_8]!=-1) return f[rest][last][llast][hf][_4][_8];
int cancse=limit?a[rest]:9;
LL res=0;
for(register int i=0;i<=cancse;i++)
{
if(i==0&&rest==11) continue;
res+=dfs(rest-1,i,last,hf||((i==last)&&(i==llast)),_4||(i==4),_8||(i==8),limit&&(i==cancse));
}
if(limit==false) f[rest][last][llast][hf][_4][_8]=res;
return res;
}
inline LL solve(LL x)
{
if(x<1e10) return 0;
m=0;
while(x) a[++m]=x%10,x/=10;
memset(f,-1,sizeof(f));
return dfs(m,-1,-1,0,0,0,1);
}
signed main()
{
L=read();R=read();
printf("%lld",solve(R)-solve(L-1));
}