被慎老师教育数位\(dp\)怎么写了

看来我数位\(dp\)的写法太落后了

这道题很显然就是一个\(AC\)自动机上的数位\(dp\),按照套路

我们可以设计\(dp[i][j][0/1]\)表示匹配了\(i\)为在自动机上的\(j\)位置,不卡/卡上界

卡上界是一个很神奇的东西,代表这一位和之前的所有位都和上界相等

如果一个状态卡着上界,我们往下选择的数只能比上界这一位上的数小或者相等,如果相等则继续卡上界,否咋就不卡上界

而如果没有卡上界的话,我们往下选什么都可以啦

而放到\(AC\)机上无非就是看看这个位置在\(fail\)树上到根的路径有没有结束标记就好了

但是这样就挂了,因为我们并没有考虑前导\(0\)的情况

于是多来一维状态,表示是否有前导\(0\),如果是前面一直是前导\(0\)之后继续填\(0\)我们就直接让其回到根上去

代码

#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
#define re register
#define LL long long
#define maxn 1505
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define pt putchar(1)
const int mod=1e9+7;
int son[maxn][10],f[maxn],fail[maxn];
int dp[1205][1500][2][2];
char S[maxn],T[maxn];
int a[maxn];
int n,L,cnt_1,F[11];
inline void ins()
{
scanf("%s",T+1);
int now=0;
int len=strlen(T+1);
for(re int i=1;i<=len;i++)
{
if(!son[now][T[i]-'0']) son[now][T[i]-'0']=++cnt_1;
now=son[now][T[i]-'0'];
}
f[now]=1;
}
inline void Build()
{
std::queue<int> q;
for(re int i=0;i<10;i++) if(son[0][i]) q.push(son[0][i]);
while(!q.empty())
{
int k=q.front();
q.pop();
f[k]|=f[fail[k]];
for(re int i=0;i<10;i++)
if(son[k][i]) fail[son[k][i]]=son[fail[k]][i],q.push(son[k][i]);
else son[k][i]=son[fail[k]][i];
}
}
int main()
{
scanf("%s",S+1),scanf("%d",&n);
for(re int i=1;i<=n;i++) ins();
Build();L=strlen(S+1);
for(re int i=1;i<=L;i++) a[i]=S[i]-'0';
dp[0][0][1][0]=1;
for(re int i=0;i<L;i++)
for(re int j=0;j<=cnt_1;j++)
for(re int o=0;o<=1;o++)
for(re int p=0;p<=1;p++)
{
if(!dp[i][j][o][p]) continue;
for(re int k=1;k<10;k++)
{
if(f[son[j][k]]) continue;
if(!o) dp[i+1][son[j][k]][0][1]=(dp[i+1][son[j][k]][0][1]+dp[i][j][o][p])%mod;
else
{
if(k<a[i+1]) dp[i+1][son[j][k]][0][1]=(dp[i+1][son[j][k]][0][1]+dp[i][j][o][p])%mod;
else if(a[i+1]==k) dp[i+1][son[j][k]][1][1]=(dp[i+1][son[j][k]][1][1]+dp[i][j][o][p])%mod;
}
}
if(p)
{
re int k=0;
if(F[k]) continue;
if(f[son[j][k]]) continue;
if(!o) dp[i+1][son[j][k]][0][1]=(dp[i+1][son[j][k]][0][1]+dp[i][j][o][p])%mod;
else
{
if(k<a[i+1]) dp[i+1][son[j][k]][0][1]=(dp[i+1][son[j][k]][0][1]+dp[i][j][o][p])%mod;
else if(a[i+1]==k) dp[i+1][son[j][k]][1][1]=(dp[i+1][son[j][k]][1][1]+dp[i][j][o][p])%mod;
}
}
else
{
re int k=0;
dp[i+1][0][0][0]=(dp[i+1][0][0][0]+dp[i][j][o][p])%mod;
}
}
int ans=0;
for(re int i=0;i<=cnt_1;i++) ans=(ans+dp[L][i][0][1]+dp[L][i][1][1])%mod;
printf("%d\n",ans);
return 0;
}

【[SDOI2014]数数】的更多相关文章

  1. 【BZOJ】【3530】【SDOI2014】数数

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

  2. BZOJ3530: [Sdoi2014]数数

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

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

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

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

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

  5. 「SDOI2014」数数 解题报告

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

  6. 3530: [Sdoi2014]数数

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

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

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

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

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

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

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

  10. [bzoj3530][Sdoi2014]数数_AC自动机_数位dp

    数数 bzoj-3530 Sdoi-2014 题目大意:给你一个整数集合,求所有不超过n的正整数,是的它的十进制表示下不能再一段等于集合中的任意数. 注释:$1\le n \le 1200$,$1\l ...

随机推荐

  1. php中continue关键字

    跳出本次循环进行下一次. 在while和do while中也可以用 $num = 0; while($num < 10) { $num ++; if($num === 5) { echo 'eq ...

  2. ContextMenustrip 控件

    ContextMenustrip 控件是由 System.Windows.Forms.ContextMenustrip类提供,也是ToolstripMenu对象的容器,用来创建窗体的右键显示的菜单,主 ...

  3. jQuery 关于IE9上传文件无法进入后台问题的原因及解决办法(ajaxfileupload.js第四弹)

    第四弹的诞生完全不在自己最初的计划之中,是有个网友看了先前关于<ajaxfileupload.js系列>的文章后提出的问题,由于自己一直是用chrome浏览器去测试demo,完全忽略IE浏 ...

  4. 面向对象(基础oop)之结构与数组高级

    大家好,我叫李京阳,,很高兴认识大家,之所以我想开一个自己的博客,就是来把自己所了解的知识点通过自己的话写一下,希望被博客园的朋友们点评和一起讨论一下,也希望从博客园中多认识一些软件开发人员!现在我开 ...

  5. 【SSH网上商城项目实战07】Struts2和Json的整合

    转自:https://blog.csdn.net/eson_15/article/details/51332758 上一节我们完成了DataGrid显示jason数据,但是没有和后台联系在一起,只是单 ...

  6. Golang的 signal

    在实际项目中我们可能有下面的需求: 1.修改了配置文件后,希望在不重启进程的情况下重新加载配置文件: 2.当用 Ctrl + C 强制关闭应用后,做一些必要的处理: 这时候就需要通过信号传递来进行处理 ...

  7. bat批处理中如何获取前一天日期

    网上找了好久在批处理中生成前一日期的代码段 但网上找到的代码对 每个月的1号和每年的1号计算前一日期时,总会报错,然后要加很多的逻辑判断 想了想,可以用.net写个EXE程序,用.net实现获取前一日 ...

  8. python中字典,没键加键,有键操作其键对应的值,的思想

    cars = ['鲁A32444', '鲁B12333', '京B8989M', '黑C49678', '黑C46555', '沪B25041', '黑C34567'] locations = {'沪 ...

  9. js在ie6下的一个bug—未结束标签的错误

    在IE6下,如果在body标签没结束前,用代码获取body对象就会出现错误.如: <html> <head> <script type="text/javasc ...

  10. 用CSS3 & jQuery创建apple TV海报视差效果

    用CSS和jQuery来实现它,尽量看起来和原效果一样. 最终效果图 本教程里,我将使用CSS,HTML和jQuery来创建一个近似Apple TV视差效果,如果你正在阅读,我假设你对上述三种技术都有 ...