题目描述

我们称一个正整数N是幸运数,当且仅当它的十进制表示中不包含数字串集合S中任意一个元素作为其子串。例如当S=(22,333,0233)时,233是幸运数,2333、20233、3223不是幸运数。
给定N和S,计算不大于N的幸运数个数。

输入

输入的第一行包含整数N。
接下来一行一个整数M,表示S中元素的数量。
接下来M行,每行一个数字串,表示S中的一个元素。

输出

输出一行一个整数,表示答案模109+7的值。

样例输入

20
3
2
3
14

样例输出

14


题解

AC自动机+数位dp

同学的某道考试题的加强版。。。

由于给定的串多且复杂,要求不能匹配到这些串,所以可以对这些串建立Trie图。

然后设$f[i][j]$表示从$j$开始走$i$个节点,不触碰到危险节点(即得到的是非幸运数)的方案数。

那么如果$j$是危险节点则方案数为0,否则枚举$j$走出去的第一步,用$f[i-1][next[j][k]]$更新$f[i][j]$。

考虑数位dp的过程:

首先处理出位数不满$n$位的数的个数:枚举位数和最高位(非0),然后方案数即为$f[i][next[1][j]]$。

然后考虑位数满$n$位的数的个数:

考虑从高到底的每一位:从0到当前位-1是满的(即后面的数恰好从0到10^{位数}),因此可以直接从$f$中取出。再考虑当前位不满的情况,此时转化为了子问题,按照同样的方法处理即可。

注意最高位是不能包含前导0的,而确定最高位以后其余的位是可以包含前导0的。

时间复杂度$O(10nL)$

细节贼多。。。代码凑合着看吧。。。

#include <queue>
#include <cstdio>
#include <cstring>
#define N 1510
#define mod 1000000007
using namespace std;
queue<int> q;
int next[N][10] , tot = 1 , fail[N] , tag[N] , f[N][N];
char s[N] , w[N];
void build()
{
int x , i;
for(i = 0 ; i < 10 ; i ++ ) next[0][i] = 1;
q.push(1);
while(!q.empty())
{
x = q.front() , q.pop() , tag[x] |= tag[fail[x]];
for(i = 0 ; i < 10 ; i ++ )
{
if(next[x][i]) fail[next[x][i]] = next[fail[x]][i] , q.push(next[x][i]);
else next[x][i] = next[fail[x]][i];
}
}
}
int main()
{
int n , m , i , j , k , t , flag , ans = 0;
scanf("%s%d" , s , &m) , n = strlen(s);
for(i = 1 ; i <= m ; i ++ )
{
scanf("%s" , w);
for(j = 0 , t = 1 ; w[j] ; j ++ )
{
if(!next[t][w[j] ^ '0']) next[t][w[j] ^ '0'] = ++tot;
t = next[t][w[j] ^ '0'];
}
tag[t] = 1;
}
build();
for(i = 1 ; i <= tot ; i ++ ) f[1][i] = !tag[i];
for(i = 2 ; i <= n ; i ++ )
for(j = 1 ; j <= tot ; j ++ )
if(!tag[j])
for(k = 0 ; k < 10 ; k ++ )
f[i][j] = (f[i][j] + f[i - 1][next[j][k]]) % mod;
for(i = 1 ; i < n ; i ++ )
for(j = 1 ; j < 10 ; j ++ )
ans = (ans + f[i][next[1][j]]) % mod;
for(i = 0 , t = flag = 1 ; i < n ; i ++ )
{
for(j = flag ; j < (s[i] ^ '0') ; j ++ ) ans = (ans + f[n - i][next[t][j]]) % mod;
t = next[t][s[i] ^ '0'];
if(tag[t]) break;
flag = 0;
}
if(!tag[t]) ans = (ans + 1) % mod;
printf("%d\n" , ans);
return 0;
}

【bzoj3530】[Sdoi2014]数数 AC自动机+数位dp的更多相关文章

  1. 【HDU3530】 [Sdoi2014]数数 (AC自动机+数位DP)

    3530: [Sdoi2014]数数 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 682  Solved: 364 Description 我们称一 ...

  2. 【JZOJ3624】【SDOI2014】数数(count) AC自动机+数位dp

    题面 100 容易想到使用AC自动机来处理禁忌子串的问题: 然后在自动机上数位dp,具体是: \(f_{i,j,0/1}\)表示填了\(i\)位,当前在自动机的第\(j\)个结点上,\(0\)表示当前 ...

  3. BZOJ 3530 [SDOI2014]数数 (Trie图/AC自动机+数位DP)

    题目大意:略 裸的AC自动机+数位DP吧... 定义f[i][x][0/1]表示已经匹配到了第i位,当前位置是x,0表示没到上限,1到上限,此时数是数量 然而会出现虚拟前导零,即前几位没有数字的情况, ...

  4. BZOJ3530:[SDOI2014]数数(AC自动机,数位DP)

    Description 我们称一个正整数N是幸运数,当且仅当它的十进制表示中不包含数字串集合S中任意一个元素作为其子串.例如当S=(22,333,0233)时,233是幸运数,2333.20233.3 ...

  5. BZOJ3530[Sdoi2014]数数——AC自动机+数位DP

    题目描述 我们称一个正整数N是幸运数,当且仅当它的十进制表示中不包含数字串集合S中任意一个元素作为其子串.例如当S=(22,333,0233)时,233是幸运数,2333.20233.3223不是幸运 ...

  6. BZOJ 3530: [Sdoi2014]数数 [AC自动机 数位DP]

    3530: [Sdoi2014]数数 题意:\(\le N\)的不含模式串的数字有多少个,\(n=|N| \le 1200\) 考虑数位DP 对于长度\(\le n\)的,普通套路DP\(g[i][j ...

  7. [SDOI2014]数数 --- AC自动机 + 数位DP

    [SDOI2014]数数 题目描述: 我们称一个正整数N是幸运数,当且仅当它的十进制表示中不包含数字串集合S中任意一个元素作为其子串. 例如当S=(22,333,0233)时,233是幸运数,2333 ...

  8. P3311 [SDOI2014]数数 AC自动机+数位DP

    题意 给定一个正整数N和n个模式串,问不大于N的数字中有多少个不包含任意模式串,输出对\(1e^9+7\)取模后的答案. 解题思路 把所有模式串都加入AC自动机,然后跑数位DP就好了.需要注意的是,这 ...

  9. HDU-4518 吉哥系列故事——最终数 AC自动机+数位DP

    题意:如果一个数中的某一段是长度大于2的菲波那契数,那么这个数就被定义为F数,前几个F数是13,21,34,55......将这些数字进行编号,a1 = 13, a2 = 21.现给定一个数n,输出和 ...

随机推荐

  1. Erwin 简单使用

    1. 物理设计:汉译英过程 ① Logical 中操作:Tools-Names-Edit Naming Standards…-Glossary选项import,导入内容为编辑好的CSV文件(只包含中文 ...

  2. SpringBoot学习12:springboot异常处理方式2(使用@ExceptionHandle注解)

    1.编写controller package com.bjsxt.controller; import org.springframework.stereotype.Controller; impor ...

  3. singnal 13 was raised

    在app运行过程中按下home键或者其他原因app被挂起,socket连接不会断开,服务器为了节省资源,在一段时间后会主动关闭这个连接.当玩家再次切回到游戏后,前端并不知道这个连接已经断开了,继续通过 ...

  4. C#进阶学习笔记(个人整理)

    学习笔记 第一章: 一.回顾数组 1.变量 : 只能存储一个数据 2.数组 :存储固定大小的相同类型的数据 3.对象 : 存储多个相同/不同类型的数据 4.集合 : 特殊的容器,存储N个相同/不同类型 ...

  5. linux下安装xtrabackup

    下载需要的版本的xtrabackup软件包,链接如下: https://www.percona.com/downloads/XtraBackup/LATEST/ percona-xtrabackup- ...

  6. Python__for循环和列表生成式的区别

    话不多,上例子 >>> L = [,,] >>> for i in range(len(L)): L[i] = L[i] + L[i-] print(L) #结果 ...

  7. 柱状图多系列php动态实现(ec)

    <?php require_once 'data.php'; $arr1=$a->sum('answer','ask_id=1'); $arr2=$a->sum('answer',' ...

  8. JavaScript高级程序设计第三版.CHM【带实例】

    从驱动全球商业.贸易及管理领域不计其数的复杂应用程序的角度来看,说 JavaScript 已经成为当今世界上最流行的编程语言一点儿都不为过. JavaScript 是一种非常松散的面向对象语言,也是 ...

  9. [Noip2016]组合数(数论)

    题目描述 组合数表示的是从n个物品中选出m个物品的方案数.举个例子,从(1,2,3) 三个物品中选择两个物品可以有(1,2),(1,3),(2,3)这三种选择方法.根据组合数的定 义,我们可以给出计算 ...

  10. spark中的RDD以及DAG

    今天,我们就先聊一下spark中的DAG以及RDD的相关的内容 1.DAG:有向无环图:有方向,无闭环,代表着数据的流向,这个DAG的边界则是Action方法的执行 2.如何将DAG切分stage,s ...