JYY 来到了一个新的城市,为了和大家保持联系,第一件事就是办理新的手机号。JYY 对号码的要求很高,希望大家都能够顺畅地阅读手机号,因此 JYY 特别研究了地球人的电话号码阅读习惯,有如下重大发现 (请自行代入你们的手机号码):地球人总是按照以下四种方式来朗读电话号码:

  1. xxx-xxx-xxxxx 例如 151-958-83019

  2. xxx-xxxx-xxxx 例如 151-9588-3019

  3. xxxx-xxxx-xxx 例如 1519-5883-019

  4. xxxx-xxx-xxxx 例如 1519-588-3019

即便是同一个电话号码,不同的人也会按照自己的习惯去解读,例如有些人会觉得电话号码是151-9588-3019,而有些却坚持 1519-588-3019。

为了让号码显得更上口,JYY 认为有些不吉利的数字串,在报电话号码时永远不应该被完整地读出来,例如,JYY 认为 7456 是不吉利的数字串 (气死我了),那么 13000007456 就是一个不好的号码,因为有人会把这个号码读作 130-000-07456,而在最后一次完整地读出了 7456。然而,13000745600 却不是一个不好的号码,因为无论怎么读,7456 都会被拆分开来。

现在给出 JYY 认为不吉利的数字串,请你计算满足 JYY 要求的电话号码,总共有多少个。具体来说说,一个好的电话号码满足以下要求:

  1. 电话号码是以 1 开头的 11 位数字串。

  2. 这个号码无论按照之前描述的 4 种读法中的哪个,都不能在任意时刻连续读出不吉利的数字串。

dp,設f[i][j]表示i位前五位為j的方案數,從後到前枚舉每一位

f[0][0]=1;枚舉更大的一位為0-9,f[i][nxt]=f[i-1][j]

然而有些方案不合法,要減去。我們可以考慮設常量數組a來表示不合法的狀態位置

則在i==a[i]的位置時,從前往後檢測是否不合法

預處理出一個數組g,g[i]表示與i相同的子串個數,且開頭從小到大在字符串的g[i][j]位

每次判定j時枚舉g的j,k位,當我們發現現在的g j k比b[l][0]要小,那麼可以取到這個值。f[i][j]不合法

最後取所有f[11][j%100000==1]的每一位即可

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll st[]={0,5,4,3,8,8,7,7,11,11},le[]={0,5,4,3,3,4,4,3,3,4},len[110],num[110],f[12][100010],n,tw[15],g[100010][110];
char s[110][20];
int main(){
    tw[0]=1;
    for(ll i=1;i<=13;i++)
        tw[i]=tw[i-1]*10;
    scanf("%lld",&n);
    for(ll i=1;i<=n;i++){
        scanf("%s",s[i]+1);
        len[i]=strlen(s[i]+1);
        for(ll j=len[i];j>=1;j--)
            num[i]=num[i]*10+s[i][j]-'0';
    }
    f[0][0]=1;
    for(ll i=1;i<=n;i++)
        for(ll j=0;j<=99999;j++){
            int v=0;
            for(ll k=1;k<=6-len[i];k++)
                if(j%tw[len[i]+k-1]/tw[k-1]==num[i]){
                    v=len[i]+k-1;
                    break;
                }
            if(v)g[j][++g[j][0]]=v;
        }
    for(ll i=1;i<=11;i++){
        for(ll j=0;j<=99999;j++)
            for(ll k=0;k<=9;k++)
                f[i][j%10000*10+k]+=f[i-1][j];
        for(ll j=1;j<=9;j++)
            if(st[j]==i)
                for(int k=0;k<=99999;k++)
                    if(f[i][k])
                        for(int l=1;l<=g[k][0];l++)
                            if(g[k][l]<=le[j]){
                                f[i][k]=0;
                                break;
                            }
    }
    ll ans=0;
    for(ll i=0;i<=99999;i++)
        if(i%10==1)
            ans+=f[11][i];
    printf("%lld",ans);
}

jzoj3363的更多相关文章

随机推荐

  1. 有关gitlab的神秘操作.....version&&domain设置...

    在使用gitlab的时候,如果服务器IP变动,之前的domain写入了配置文件了,如下路径: [root@gitlab-server ~]# vim /var/opt/gitlab/gitlab-ra ...

  2. PAT 1034 有理数四则运算(20)(代码框架+思路+测试点错误分析)

    1034 有理数四则运算(20)(20 分)提问 本题要求编写程序,计算2个有理数的和.差.积.商. 输入格式: 输入在一行中按照"a1/b1 a2/b2"的格式给出两个分数形式的 ...

  3. 三维dem

    关注World wind Java,<World wind Java三维地理信息系统开发指南随书光盘 1. 下载worldwind java sdk 下载地址:http://builds.wor ...

  4. 在EF中使用MySQL的方法及常见问题

    有时需要在网上租用空间或数据库,Mysql成本低一些,所以想将sql server转成mysql…… 注意:在安装Mysql时要选择文字集为utf8,否则将不能使用中文(当前也可以在创建数据库时使用u ...

  5. AJAX初尝试——ACM/ICPC类比赛气球管理系统

    很早之前做过一个,白板没界面,20秒暴力刷新,数据库每个team一个n列的对应n个题目的标记项,只能对单个比赛暴力把全部user_id导入单独的气球表(也就是cid=1000用这个表的话,cid100 ...

  6. Find the squareroot

    https://github.com/Premiumlab/Python-for-Algorithms--Data-Structures--and-Interviews/blob/master/Moc ...

  7. 面向对象先修:Java入门

    学习总结 在C语言和数据结构的基础上,在上暑期的面向对象Java先修课程时,熟悉语言的速度明显加快了很多.Java和C在很多基础语法上非常相似,比如基本的数据类型,循环以及条件分支语句,数组的遍历等. ...

  8. 2018.10.18 bzoj1185: [HNOI2007]最小矩形覆盖(旋转卡壳)

    传送门 不难看出最后的矩形一定有一条边与凸包某条边重合. 因此先求出凸包,然后旋转卡壳求出当前最小矩形面积更新答案. 代码: #include<bits/stdc++.h> #define ...

  9. 2018.10.05 NOIP模拟 阶乘(简单数论)

    传送门 签到题. 直接把所有数先质因数分解. 同时统计每一个在阶乘中会出现的质数出现的最少次数. 然后对于每一个这样的质数,我们求出满足其出现质数的m的最小值,然后求出所有m的最大值. 求m的时候可以 ...

  10. struct的使用

    编写一个学生struct,成员有学号(id).姓名(name).成绩(5门课程),随机生成多个学生的学号.姓名和成绩存储到结构体数组.再根据总分进行排名并输出学生的信息和总分. stu.h #ifnd ...