luogu P4124 [CQOI2016]手机号码 数位dp

#include<map>
#include<queue>
#include<time.h>
#include<limits.h>
#include<cmath>
#include<ostream>
#include<iterator>
#include<set>
#include<stack>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define rep_1(i,m,n) for(int i=m;i<=n;i++)
#define mem(st) memset(st,0,sizeof st)
int read()
{
	int res=0,ch,flag=0;
	if((ch=getchar())=='-')             //判断正负
		flag=1;
	else if(ch>='0'&&ch<='9')           //得到完整的数
		res=ch-'0';
	while((ch=getchar())>='0'&&ch<='9')
		res=res*10+ch-'0';
	return flag?-res:res;
}
typedef long long ll;
typedef pair<int,int> pii;
typedef unsigned long long ull;
typedef pair<double,double> pdd;
const int inf = 0x3f3f3f3f;
//  poj	  poj+1 +2 =3  _4  _8
#define int long long
int dp[13][11][11][2][2][2][2];
int num[13];
int cnt;
int l,r;
int dfs(int poj,int pre1,int pre2,int c,bool limit,bool _4,bool _8)
{
	if(_4&&_8)
		return 0;
	if(poj<=0)
		return c;
	if(dp[poj][pre1][pre2][c][limit][_4][_8]!=-1)
		return dp[poj][pre1][pre2][c][limit][_4][_8];
	int up=limit?num[poj]:9;
	ll ans=0;
	for(int i=0; i<=up; i++)
		ans+=dfs(poj-1,i,pre1,c||(i==pre1&&i==pre2),limit&&i==num[poj],_4||i==4,_8||i==8);
	return dp[poj][pre1][pre2][c][limit][_4][_8]=ans;
}
int solve(int x)
{
	if(x<1e10)
		return 0;
	cnt=0;
	memset(dp,-1,sizeof dp);
	while(x)
	{
		num[++cnt]=x%10;
		x/=10;
	}
	ll ans=0;
	for(int i=1; i<=num[cnt]; i++)
		ans+=dfs(10,i,0,0,i==num[cnt],i==4,i==8);
	return ans;
}
signed main()
{
	cin>>l>>r;
	cout<<solve(r)-solve(l-1)<<endl;
	return 0;
}
posted @ 2020-05-04 22:59  晴屿  阅读(125)  评论(0编辑  收藏  举报