真的很开心呢,总算是有一道完完全全由自己做出来的题目啦~

这一道题目洛谷P3311和另一道JSOI文本生成器的题目是十分相像的,dp方面几乎相同。只是<=n的约束,让这道题目必须结合数位dp的方法,新建一个维度代表之后数字的大小是否受到限制。0代表受限,1代表不受限。但是处理前导零的部分的确较为头痛,最后采取的方法是在第一次dp的时候不允许有前导零的存在,在第二次dp的时候才把这一部分的答案统计出来。所以在第二次的dp转移中,一个节点只能由父亲节点、而不能由Fail节点转移而来。

#include <bits/stdc++.h>
using namespace std;
#define maxn 2000
#define mod 1000000007
int m, cnt = , len, ans, ch[maxn][], dp[maxn][maxn][], fail[maxn];
bool error[maxn];
string n, s;
struct AC_Automation
{
void Trie_ins()
{
int now = , len = s.length();
for(int i = ; i < len; i ++)
{
if(!ch[now][s[i] - '']) ch[now][s[i] - ''] = ++ cnt;
now = ch[now][s[i] - ''];
}
error[now] = true;
} void AC_build()
{
queue <int> q;
q.push();
while(!q.empty())
{
int u = q.front();
q.pop();
for(int i = ; i < ; i ++)
{
if(ch[u][i])
{
int v = ch[u][i], k = fail[u];
while(!ch[k][i]) k = fail[k];
fail[v] = ch[k][i];
if(error[fail[v]]) error[v] = true;
q.push(v);
}
else ch[u][i] = ch[fail[u]][i];
}
}
}
}ACM; void DP(int x)
{
for(int i = ; i <= cnt; i ++)
{
if(error[i] || (!dp[x - ][i][] && !dp[x - ][i][])) continue;
for(int j = ; j < ; j ++)
{
if(x == && j == ) continue;
int k = i;
while(!ch[k][j]) k = fail[k];
int v = ch[k][j];
if(j == n[x - ] - '') dp[x][v][] = (dp[x][v][] + dp[x - ][i][]) % mod;
if(j < n[x - ] - '') dp[x][v][] = (dp[x][v][] + dp[x - ][i][]) % mod;
dp[x][v][] = (dp[x][v][] + dp[x - ][i][]) % mod;
}
}
} void DP2()
{
dp[][][] = ;
for(int x = ; x < len; x ++)
for(int i = ; i <= cnt; i ++)
{
if(error[i] || !dp[x - ][i][]) continue;
for(int j = ; j < ; j ++)
{
if(x == && j == ) continue;
int k = i;
int v = ch[k][j];
dp[x][v][] = (dp[x][v][] + dp[x - ][i][]) % mod;
}
}
for(int i = ; i < len; i ++)
for(int j = ; j <= cnt; j ++)
if(!error[j]) ans = (ans + dp[i][j][]) % mod;
} int main()
{
cin >> n;
cin >> m;
for(int i = ; i < ; i ++) ch[][i] = ;
for(int i = ; i <= m; i ++)
{
cin >> s;
ACM.Trie_ins();
}
ACM.AC_build();
len = n.length();
dp[][][] = ;
for(int i = ; i <= len; i ++) DP(i);
for(int i = ; i <= cnt; i ++)
if(!error[i]) ans = (ans + dp[len][i][] + dp[len][i][]) % mod;
memset(dp, , sizeof(dp));
DP2();
printf("%d\n", ans);
return ;
}

【题解】SDOI2014数数的更多相关文章

  1. 题解-[SDOI2014]数数

    [SDOI2014]数数 这题的前置知识是AC自动机和dp,前置题目是 [JSOI2007]文本生成器,前置题目我写的题解 题解-[JSOI2007]文本生成器.我的讲解假设你做过上面那道题. 这题比 ...

  2. BZOJ3530: [Sdoi2014]数数

    3530: [Sdoi2014]数数 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 322  Solved: 188[Submit][Status] ...

  3. 【BZOJ】【3530】【SDOI2014】数数

    AC自动机/数位DP orz zyf 好题啊= =同时加深了我对AC自动机(这个应该可以叫Trie图了吧……出边补全!)和数位DP的理解……不过不能自己写出来还真是弱…… /************* ...

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

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

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

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

  6. 「SDOI2014」数数 解题报告

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

  7. 3530: [Sdoi2014]数数

    3530: [Sdoi2014]数数 链接 分析: 对给定的串建立AC自动机,然后数位dp.数位dp的过程中,记录当前在AC自动机的哪个点上,保证不能走到出现了给定串的点. 代码: #include& ...

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

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

  9. bzoj [Sdoi2014]数数 AC自动机上dp

    [Sdoi2014]数数 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 1264  Solved: 636[Submit][Status][Discu ...

  10. [Sdoi2014]数数[数位dp+AC自动机]

    3530: [Sdoi2014]数数 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 834  Solved: 434[Submit][Status][ ...

随机推荐

  1. Python学习笔记:第2天while循环 运算符 格式化输出 编码

    目录 1. while循环 continue.break和else语句 2. 格式化输出 3. 运算符 3.1 算数运算 3.2 比较运算符 3.3 赋值运算符 3.4 逻辑运算符 3.5 成员运算符 ...

  2. Excel学习路径总结

    本片涉及从入门到Excel的各个方向,包含众多资料和自己学习的心得,希望您可以仔细阅之:   入门篇: 无论是软件,还是编程,最好的入门就是通过看视频来学习,视频优点为很容易看清楚,手把手教授,不容易 ...

  3. atoi 和 atof (把数字字符串转化为数字储存)

    int atoi(char *s) 如果字符串内容是整数就返回该整数,否则返回0 double atof(char *s) 同上,不过返回浮点型 #include<iostream> #i ...

  4. itchat和matplotlib的结合使用爬取微信信息

    前几天无意中看到了一片文章,<一件有趣的事:我用 Python 爬了爬自己的微信朋友>,这篇文章写的是使用python中的itchat爬取微信中朋友的信息,其中信息包括,昵称.性别.地理位 ...

  5. MFC接收ShellExecute多个参数

    在应用程序开发过程中,我们经常需要带参数启动另一个执行程序,如何传递多个参数,如何解析多个参数呢?   传参数 传递参数可使用ShellExecute函数,示例如下: ShellExecute(NUL ...

  6. Android开发——Android手机屏幕适配方案总结

    )密度无关像素,单位为dp,是Android特有的单位 Android开发时通常使用dp而不是px单位设置图片大小,因为它可以保证在不同屏幕像素密度的设备上显示相同的效果. /** * dp与px的转 ...

  7. PIC24 通过USB在线升级 -- USB CDC bootloader

    了解bootloader的实现,请加QQ: 1273623966 (验证填bootloader):欢迎咨询或定制bootloader:我的博客主页www.cnblogs.com/geekygeek 今 ...

  8. OrCAD把原理图中的器件添加到原理图库

    1. 在使用OrCAD的时候,有时需要把别人的原理图里面的器件添加到自己的原理图库,方便以后使用,具体操作如下,依次选择Design Cache---元器件--Copy 2. 选中要存放的原理图库,鼠 ...

  9. IOException: win32 io returned 267. Path:

    unity3d在导出android项目时出现了这个错误,找了一圈也没找到原因,最后把项目名中空格去掉后OK了,坑啊!!!!

  10. Git 上传本地仓库到码云

    一.将本地的项目上传到码云 1.码云上创建一个项目 testgit (名字随你) 2.本地创建一个文件夹D:/testgit,然后使用git bash 3.cd 到本地文件夹中D:/testgit 4 ...