loj #2044. 「CQOI2016」手机号码

#2044. 「CQOI2016」手机号码

内存限制:256 MiB时间限制:1000 ms标准输入输出
题目类型:传统评测方式:文本比较
上传者: 匿名

题目描述

人们选择手机号码时都希望号码好记、吉利。比如号码中含有几位相邻的相同数字、不含谐音不吉利的数字等。手机运营商在发行新号码时也会考虑这些因素,从号段中选取含有某些特征的号码单独出售。为了便于前期规划,运营商希望开发一个工具来自动统计号段中满足特征的号码数量。

工具需要检测的号码特征有两个:号码中要出现至少 333 个相邻的相同数字;号码中不能同时出现 888 和 444。号码必须同时包含两个特征才满足条件。满足条件的号码例如:13000988721、23333333333、14444101000。而不满足条件的号码例如:1015400080、10010012022。

手机号码一定是 111111 位数,前不含前导的 000。工具接收两个数 LLL 和 RRR,自动统计出 [L,R][L, R][L,R] 区间内所有满足条件的号码数量。LLL 和 RRR 也是 111111 位的手机号码。

输入格式

输入文件内容只有一行,为空格分隔的两个正整数 L,RL, RL,R。

输出格式

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

样例

样例输入

12121284000 12121285550

样例输出

5

样例解释

满足条件的号码有:12121285000、 12121285111、 12121285222、 12121285333、 12121285550。

数据范围与提示

对于 30%30\%30% 的数据,R−L≤107R - L \leq 10^7RL107​​;
对于 100%100\%100% 的数据,1010≤L≤R<101110^{10} \leq L \leq R < 10^{11}1010​​LR<1011​​。

 

 

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int a[20];
long long l,r,f[20][10][10][2][2][2];
long long dfs(int pos,int p1,int p2,bool p3,bool p4,bool p8,bool limit) {
    if(p4&&p8) return 0;
    if(pos==0) {return p3;}
    if(!limit && f[pos][p1][p2][p3][p4][p8]!=-1)return f[pos][p1][p2][p3][p4][p8];
    int End=9;
    if(limit)End=a[pos];
    long long ans=0;
    for(int i=0;i<=End;i++)
        ans+=dfs(pos-1,p2,i,(p1==p2&&p2==i)||p3,(i==4)||p4,(i==8)||p8,limit&&(i==a[pos]));
    if(!limit)f[pos][p1][p2][p3][p4][p8]=ans;
    return ans;
}
long long solve(long long x) {
    int len=0;
    while(x){
        len++;
        a[len]=x%10;
        x/=10LL;
    }
    long long res=0;
    for(int i=1;i<=a[len];i++)
        res+=dfs(len-1,0,i,0,i==4,i==8,i==a[len]);
    return res;
}
int main() {
    memset(f,-1,sizeof(f));
    cin>>l>>r;
    if(l==10000000000) cout<<solve(r);
    else cout<<solve(r)-solve(l-1);
    return 0;
}

 

posted @ 2018-04-22 15:11  Echo宝贝儿  阅读(173)  评论(0编辑  收藏  举报