Cellphone Number手机号码

3820: 手机号码

题目描述

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

输入

有多行数据输入
每行为空格分隔的 2 个正整数 L, R。

输出

输出内容只有一行,为 1 个整数,表示满足条件的手机号数量。

样例输入

12121284000 12121285550

样例输出

5

提示

满足条件的号码:12121285000、12121285111、12121285222、12121285333、12121285550
对于 100% 的测试数据,10^10 ≤ L ≤ R < 10^11

#include 
#define ll long long
using namespace std;
ll dp[11][3][10][2][2],L,R;
int bit[30];
ll dfs(int pre,int len,int pos,bool is4,bool is8,bool isok){
    if (pos<0) return (len>2&&!(is4&&is8));
    if (is4&&is8) return 0;
    if (isok&&dp[pos][len][pre][is4][is8]+1) return dp[pos][len][pre][is4][is8];
    ll sum=0;
    int l,mxn=(isok)?9:bit[pos];
    for (int i=mxn;i>=0;--i){
        if (len>=3) l=3;
        else if (i==pre) l=len+1;
        else l=1;
        sum+=dfs(i,l,pos-1,is4||i==4,is8||i==8,isok||iif (isok) dp[pos][len][pre][is4][is8]=sum;
    return sum;
}
ll solve(ll n) {
    if (n <= 9999999999) return 0;
    for (int i=0;i<11;++i)
        bit[i]=n%10,n/=10;
    ll sum = 0;
    for (int i=1;i<=bit[10];++i)
        sum+=dfs(i,1,9,i==4,i==8,i10]);
    return sum;
}
int main() {
    memset(dp,-1,sizeof dp);
    while(~scanf("%lld%lld",&L,&R)) {
        printf("%lld\n",solve(R)-solve(L-1));
    }
    return 0;
}

你可能感兴趣的:(DP)