zl程序教程

您现在的位置是:首页 >  其它

当前栏目

Luogu P4124 [CQOI2016]手机号码 题解

题解 手机号码 Luogu
2023-06-13 09:12:49 时间

Luogu P4124 [CQOI2016]手机号码 题解

Describe

题目链接

人们选择手机号码时都希望号码好记、吉利。比如号码中含有几位相邻的相同数字、不含谐音不吉利的数字等。手机运营商在发行新号码时也会考虑这些因素,从号段中选取含有某些特征的号码单独出售。为了便于前期规划,运营商希望开发一个工具来自动统计号段中满足特征的号码数量。 工具需要检测的号码特征有两个:号码中要出现至少 3 个相邻的相同数字;号码中不能同时出现 84。号码必须同时包含两个特征才满足条件。满足条件的号码例如:13000988721、23333333333、14444101000。而不满足条件的号码例如:1015400080、10010012022。 手机号码一定是 11 位数,前不含前导的 0。工具接收两个数 LR,自动统计出 [L,R] 区间内所有满足条件的号码数量。LR 也是 11 位的手机号码。

Solution

数位dp 注意细节

Code

#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%10;
        n/=10;
    }
    return DFS(m,-1,-1,0,0,0,1,1);
}
int L,R;
signed main(){
    scanf("%lld%lld",&L,&R);
    printf("%lld\n",solve(R)-solve(L-1));
}