洛谷P4124 [CQOI2016] 手机号码 数位dp

给出两个长度为 11 11 11位数的手机号码,求问中间有多少满足包含了连续 3 3 3位相同的数,但是不同时包含 8 8 8 4 4 4的数量。
确定是 11 11 11位,所以不含有前导 0 0 0,只要在处理第一位的时候不为 0 0 0即可。然后直接数位dp。

#include
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const ll INF=LONG_LONG_MAX;
int a[13]; 
int len; 
ll dp[20][11][11][2][2][2][2]; 
ll dfs(int pos,int pre1,int pre2,bool _8,bool _4,bool _3,bool lim) {
	if(_8&&_4) return 0;
	if(pos==0) return _3;
	ll &res=dp[pos][pre1][pre2][_8][_4][_3][lim];
	if(res!=-1) return res;
	int up=lim?a[pos]:9;
	ll ans=0;
	for(int i=0;i<=up;i++) {
		if(pos==len&&i==0) continue;
		ans+=dfs(pos-1,pre2,i,_8||(i==8),_4||(i==4),_3||(i==pre1&&pre1==pre2),lim&&i==a[pos]);
	} 
	return res=ans;
}
ll solve(ll x) {
	if(x<1e10) return 0;
	memset(dp,-1,sizeof(dp));
	len=0;
	while(x) {
		a[++len]=x%10;
		x/=10;
	}
	return dfs(len,10,10,0,0,0,1);
}
int main() {
	ll l,r;
	scanf("%lld%lld",&l,&r);
	printf("%lld\n",solve(r)-solve(l-1));
	return 0;
}

你可能感兴趣的:(比赛题解)