2018.08.19【2018提高组】模拟A组 题解 (JZOJ3363)Number

7 篇文章 0 订阅
1 篇文章 0 订阅

T2:

Number

题目描述

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 种读法中的哪个,都不能在任意时刻连续读出不吉利的数字串。

输入描述

输入文件第一行包括一个整数 n,表示 JYY 认为不吉利的数字串的数量。
接下来 n 行,每行一个不超过 5 的数字串,表示一个 JYY 认为不吉利的号码。

输出描述

输出一行,为满足条件的电话号码总数。

样例输入

1
7456

样例输出

9996000100

题解:
本来正解是自动机,但由于数据太小,我们可以考虑用DP。
设f[i][j]表示从高到低枚举到第i位,结尾四位数为j(0<=j<=9999)的方案数。
我们读入每个串后,存下其长度(由于不用字符串会省略前导0,所以一定要用),
将其转为数x,由其x mod 10向x div 10连一条边,表示当结尾为x div 10时,不能选x mod 10
预处理一下长度为ss的不可行串在第i位能否被连起来读,
然后我们枚举i和j,再枚举第i+1位选哪个数(初始值为f[1,1]=1,其它为0),然后看一下被选的数前面能否接当前结尾,
如果可以就更新f[i+1,(j*10+k)mod 10],否则看一下该长度的串在这个位置能否被连起来读,如果可以就退出,否则还是更新
至于如何查看被选的数前面能否接当前结尾:
我们将结尾当成四位的(即将20视作0020),再去查看不可行串是否为结尾的后缀,如果是就说明不可行。

长度为1~a[i]的串在位置i能被连起来读:a【1~11】=1,2,3,4,2,3,4,4,3,4,5
最后注意一下,有前导0的数可能会被省略前导0,所以我们一定要判完其长度才行
还有不可行串的长度去掉x mod 10并除以10后要减1(因为是拿x div 10去与结尾比较)
没了。
祝你好运。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值