【bzoj3530】【sdoi2014】【数数】【AC自动机+数位dp】
2016-07-08 08:27
483 查看
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
203
2
3
14
Sample Output
14HINT
下表中l表示N的长度,L表示S中所有串长度之和。1 < =l < =1200 , 1 < =M < =100 ,1 < =L < =1500
题解:
S中的串可能会有前导0,所以我们把串反过来,然后反着dp.
首先对S中的所有反串建AC自动机.
f[i][j][0/1]表示到倒数第i位,匹配到AC自动机的第j个节点,是否比原数小.
枚举i,j,0/1转移即可.在dp的过程中可以顺便统计答案.
代码:
#include<iostream> #include<cstdio> #include<cstring> #define N 2010 #define P 1000000007 int n,a [10],pos ,m,q ,fail ,ans,f [2],cnt=1; char ch ,s ; using namespace std; int read(){ int x(0);char ch=getchar(); while (ch<'0'||ch>'9') ch=getchar(); while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar(); return x; } void insert(){ int len=strlen(ch),now=1; for (int i=len-1;i>=0;i--){ int u=ch[i]-'0'; if (a[now][u]) now=a[now][u]; else a[now][u]=++cnt,now=a[now][u]; } pos[now]=1; } void getfail(){ int h(0),t(1); q[0]=1;fail[1]=0; while (h<t){ int u=q[h++]; for (int i=0;i<=9;i++){ if (!a[u][i]) continue; int k=fail[u]; while (!a[k][i]) k=fail[k]; fail[a[u][i]]=a[k][i]; if (pos[a[k][i]]) pos[a[u][i]]=1; q[t++]=a[u][i]; } } } int main(){ // freopen("a.in","r",stdin); // freopen("a.out","w",stdout); scanf("%s",s); m=read();n=strlen(s); for (int i=0;i<=9;i++) a[0][i]=1; for (int i=1;i<=m;i++){ scanf("%s",ch); insert(); } getfail(); //for (int i=1;i<=cnt;i++) cout<<fail[i]<<endl; f [1][0]=1; for (int i=n;i>=1;i--) for (int j=1;j<=cnt;j++) for (int p=0;p<=1;p++) if (f[i][j][p]) for (int k=0;k<=9;k++){ int u=s[i-1]-'0',t=j,o; while (!a[t][k]) t=fail[t]; t=a[t][k];if (pos[t]) continue; o=k>u||(k==u&&p);(f[i-1][t][o]+=f[i][j][p])%=P; if (k&&!(i==1&&o)) (ans+=f[i][j][p])%=P; } cout<<ans<<endl; }
相关文章推荐
- hibernate多表关联的简单写法
- 彩票小例子
- 16.14
- 函数
- 我们是怎么做Code Review的
- eval简单用法
- linux shell 中的sleep命令
- 数组打乱小例子
- binding.BindingException: Invalid bound statement(not found)
- Java中Collection集合
- Eclipse调试问题 adb connection Error:远程主机强迫关闭了一个现有的连接
- tab切换
- binding.BindingException: Invalid bound statement(not found)
- 数组
- 23种设计模式
- 仪表电机抖动问题的一种程序bug可能性
- oracle递归查询
- Ambari学习笔记
- 循环嵌套
- 【iOS】UITabView/UICollectionView 全选问题