Luogu P4124 [CQOI2016]手机号码 题解
Describe
题目链接
人们选择手机号码时都希望号码好记、吉利。比如号码中含有几位相邻的相同数字、不含谐音不吉利的数字等。手机运营商在发行新号码时也会考虑这些因素,从号段中选取含有某些特征的号码单独出售。为了便于前期规划,运营商希望开发一个工具来自动统计号段中满足特征的号码数量。 工具需要检测的号码特征有两个:号码中要出现至少 3 个相邻的相同数字;号码中不能同时出现 8 和 4。号码必须同时包含两个特征才满足条件。满足条件的号码例如:13000988721、23333333333、14444101000。而不满足条件的号码例如:1015400080、10010012022。 手机号码一定是 11 位数,前不含前导的 0。工具接收两个数 L 和 R,自动统计出 [L,R] 区间内所有满足条件的号码数量。L 和 R 也是 11 位的手机号码。
Solution
数位dp 注意细节
Code
代码语言:javascript复制#include<bits/stdc .h>
#define int long long
using namespace std;
int a[15],m,f[15][10][10][2][2][2][2][2];
inline int DFS(int x,int las,int lasqr,int has,int is4,int is8,int lim,int st){
if(is4&&is8) return 0;
if(x==0) return has;
if(~f[x][las][lasqr][has][is4][is8][lim][st]) return f[x][las][lasqr][has][is4][is8][lim][st];
int Max=lim?a[x]:9,res=0;
for(int i=0;i<=Max;i )
if(st==1) res =DFS(x-1,i,las,has,is4(i==4),is8(i==8),lim&&(i==Max),st&&(i==0));
else res =DFS(x-1,i,las,has(las==lasqr&&las==i),is4(i==4),is8(i==8),lim&&(i==Max),st&&(i==0));
return f[x][las][lasqr][has][is4][is8][lim][st]=res;
}
inline int solve(int n){
m=0;memset(f,-1,sizeof(f));
while(n){
a[ m]=n;
n/=10;
}
return DFS(m,-1,-1,0,0,0,1,1);
}
int L,R;
signed main(){
scanf("%lld%lld",&L,&R);
printf("%lldn",solve(R)-solve(L-1));
}