P4124 [CQOI2016]手机号码

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^+ xN+满足 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));
}
©️2020 CSDN 皮肤主题: 精致技术 设计师:CSDN官方博客 返回首页