3530: [Sdoi2014]数数
来源:互联网 发布:平安证券炒股软件 编辑:程序博客网 时间:2024/05/24 07:13
Description
我们称一个正整数N是幸运数,当且仅当它的十进制表示中不包含数字串集合S中任意一个元素作为其子串。例如当S=(22,333,0233)时,233是幸运数,2333、20233、3223不是幸运数。
给定N和S,计算不大于N的幸运数个数。
Input
输入的第一行包含整数N。接下来一行一个整数M,表示S中元素的数量。接下来M行,每行一个数字串,表示S中的一个元素。
Output
输出一行一个整数,表示答案模109+7的值。
Sample Input
2032314
Sample Output
14
HINT
下表中l表示N的长度,L表示S中所有串长度之和。
1 < =l < =1200 , 1 < =M < =100 ,1 < =L < =1500
题解
就先建一个AC自动机
然后做一下数位DP就好了
代码很丑,看看数组的表示就好了
要注意的是,2和02不是一个东西
#include<cstdio>#include<algorithm>#include<iostream>#include<cstring>#include<queue>using namespace std;const int MOD=1e9+7;const int N=1505;struct node{ int son[10],fail; bool tf;//是不是终点 }s[N];int num=0;char ss[N];int m;void init (int x){ //printf("%d\n",x); s[x].tf=false;s[x].fail=0; for (int u=0;u<10;u++) s[x].son[u]=-1;}void bt (){ int len=strlen(ss),now=0; for (int u=0;u<len;u++) { int x=ss[u]-'0'; if (s[now].son[x]==-1) { s[now].son[x]=++num; init(num); } now=s[now].son[x]; } //printf("YES:%d\n",now); s[now].tf=true;}queue<int> q;void bfs (){ int x;q.push(0); while (!q.empty()) { int x=q.front(); for (int u=0;u<10;u++) { int son=s[x].son[u],f=s[x].fail; if (son>=0) { if (x==0) s[son].fail=0; else s[son].fail=s[f].son[u]; q.push(son); } else { if (x==0) s[x].son[u]=0; else s[x].son[u]=s[f].son[u]; } } q.pop(); }}bool vis[N];void dfs (int x){ if (vis[x]) return ; vis[x]=true; int Fail=s[x].fail; dfs(Fail); s[x].tf=(s[x].tf|s[Fail].tf);}char n[N];int ooo;int f[N][2][2][N];int solve (int x,bool tf,bool tf1,int y)//当前到第几位了 是否已经小了 是否非0位 在AC自动机上是哪一位{ if (tf1==false) y=0; if (s[y].tf==true) return 0;// printf("%d %d %d %d\n",x,tf,tf1,y); if (x>ooo) return tf1==false?0:1; if (f[x][tf][tf1][y]!=0) return f[x][tf][tf1][y]; if (tf==true)//可以随便填 { f[x][tf][tf1][y]=(f[x][tf][tf1][y]+solve(x+1,true,tf1,s[y].son[0]))%MOD;//填0 for (int u=1;u<=9;u++) { // printf("NO:%d %d %d %d\n",x,u,solve(x+1,true,true,s[y].son[u]),s[y].son[u]); f[x][tf][tf1][y]=(f[x][tf][tf1][y]+solve(x+1,true,true,s[y].son[u]))%MOD; } } else { int now=n[x]-'0'; if (0!=now) f[x][tf][tf1][y]=(f[x][tf][tf1][y]+solve(x+1,true,tf1,s[y].son[0]))%MOD; for (int u=1;u<now;u++) f[x][tf][tf1][y]=(f[x][tf][tf1][y]+solve(x+1,true,true,s[y].son[u]))%MOD; if (now==0) f[x][tf][tf1][y]=(f[x][tf][tf1][y]+solve(x+1,false,tf1,s[y].son[now]))%MOD; else f[x][tf][tf1][y]=(f[x][tf][tf1][y]+solve(x+1,false,true,s[y].son[now]))%MOD; }// printf("YES:%d %d %d %d %d\n",x,tf,tf1,y,f[x][tf][tf1][y]); return f[x][tf][tf1][y]; }int main(){ memset(f,0,sizeof(f)); scanf("%s",n+1); ooo=strlen(n+1); scanf("%d",&m); init(0); for (int u=1;u<=m;u++) { scanf("%s",ss); bt(); } bfs(); memset(vis,false,sizeof(vis));vis[0]=true; for (int u=1;u<=num;u++) { //if (s[u].tf) printf("OZY:%d\n",u); dfs(u); } printf("%d\n",(solve(1,false,false,0)+MOD)%MOD); return 0;}
阅读全文
0 0
- 【BZOJ 3530】 [Sdoi2014]数数
- BZOJ 3530 【Sdoi2014】 数数
- 3530: [Sdoi2014]数数
- bzoj 3530 [Sdoi2014]数数
- 3530: [Sdoi2014]数数
- bzoj 3530: [Sdoi2014]数数
- [SDOI2014]数数
- 【SDOI2014】数数
- 【SDOI2014】数数
- [bzoj3530][SDOI2014]数数
- [SDOI2014][JZOJ3624]数数
- bzoj3530【SDOI2014】数数
- bzoj3530: [Sdoi2014]数数
- BZOJ3530 [SDOI2014]数数
- bzoj 3530: [Sdoi2014]数数 AC自动机&动态规划
- bzoj 3530: [Sdoi2014]数数 (AC自动机+数位DP)
- 【AC自动机+数位DP】SDOI2014 数数
- [BZOJ3530] [Sdoi2014]数数 && AC自动机+dp
- BZOJ 2140 稳定婚姻
- c++11 chrono全面解析(最高可达纳秒级别的精度)
- niginx.conf文件的结构说明
- 9月份学习目标
- 树状数组总结~
- 3530: [Sdoi2014]数数
- 欢迎使用CSDN-markdown编辑器
- AJAX详解
- 滴滴2018秋招编程题
- Eclipse中还原被误删的文件
- javascript 三种弹出对话框
- 2017乌鲁木齐赛区网络赛 I Colored Graph(计数)(三角trick)
- 非静态内部类中为什么不能存在静态变量
- spring boot创建过程中的问题