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;
}
posted @ 2018-09-10 19:22  lokiii  阅读(162)  评论(0编辑  收藏  举报