codeforces 585F. Digits of Number Pi

来源:互联网 发布:ubuntu开机自启动mongo 编辑:程序博客网 时间:2024/05/29 10:33

AC自动机和数位dp都写挂了….我是不是该退役了…

问L~R有多少个数满足数字里包含一个长度至少为d/2的给定串的子串

如果包含了一个长度大于d/2的子串,也一定包含长度为d/2的子串
所以相当于问L~R有多少个数满足数字里包含一个长度为d/2的给定串的子串
我们把原串所有长度为d/2的子串建到AC自动机上
因为d<=50,所以点数最大不超过25000(实际上最大值应该也比这个小很多)
所以就可以直接数位dp了
f[i][j][k][x]表示dp到第i位,前面是否有前导0,前面是否顶格,走到AC自动机上的x节点的方案数
本来还要加一维表示是否已经有长度为d/2的子串了,但是我灵机一动,每个长度为d/2的子串的结束节点的所有孩子都指向他自己,就可以省掉这一维了

code:

#include<set>#include<map>#include<deque>#include<queue>#include<stack>#include<cmath>#include<ctime>#include<bitset>#include<string>#include<vector>#include<cstdio>#include<cstdlib>#include<cstring>#include<climits>#include<complex>#include<iostream>#include<algorithm>#define ll long longusing namespace std;const int maxp = 110000;const int maxn = 1100;const ll Mod = 1e9+7;struct trie{    int son[10],fail;}tr[maxp]; int root,tot;bool v[maxp];void ins(char s[],const int l,const int r){    int x=root;    for(int i=l;i<r;i++)    {        const int w=s[i]-'0';        int &y=tr[x].son[w];        if(!y) y=++tot;        x=y;    }    v[x]=true;}char str[maxn]; int n,d;queue<int>q;void build(){    n=strlen(str); int D=d/2;    root=tot=0;    for(int i=0;i+D-1<n;i++) ins(str,i,i+D);    q.push(root);    while(!q.empty())    {        const int x=q.front(); q.pop();        if(v[x]) for(int i=0;i<10;i++) tr[x].son[i]=x;        else        {            for(int i=0;i<10;i++)            {                int &y=tr[x].son[i],fl=tr[x].fail;                if(y)                 {                    if(x!=root) tr[y].fail=tr[fl].son[i];                    q.push(y);                }                else y=tr[fl].son[i];            }        }    }}char A[maxn],B[maxn];//  rol 0 upll f[2][2][2][maxp];ll cal(char s[]){    int now=0;     memset(f,0,sizeof f); f[now][1][1][0]=1;    for(int p=0;p<d;p++)    {        now=!now;        for(int i=0;i<2;i++) for(int j=0;j<2;j++)        {            for(int x=0;x<=tot;x++) if(f[!now][i][j][x])            {                ll tmp=f[!now][i][j][x]%Mod; f[!now][i][j][x]=0;                int uk=j?s[p]-'0':9;                for(int k=0;k<=uk;k++)                {                    int ni=i&(k>0?0:1),nj=j&(k==uk?1:0),y=(!k&&i)?0:tr[x].son[k];                    f[now][ni][nj][y]+=tmp;                }            }        }    }    ll re=0;    for(int i=0;i<2;i++) for(int j=0;j<2;j++) for(int x=0;x<=tot;x++) if(v[x]&&f[now][i][j][x])        (re+=f[now][i][j][x]%Mod)%=Mod;    return re;}int t[maxn],tp;bool judge(int x){    int tp=0; while(x) t[++tp]=x%10,x/=10;    x=root;    for(int i=tp;i>=1;i--) x=tr[x].son[t[i]];    return v[x];}int main(){    scanf("%s",str);    scanf("%s%s",A,B); d=strlen(A);    build();    ll ans=cal(B)-cal(A);    int x=root;    for(int i=0;i<d;i++) x=tr[x].son[A[i]-'0'];    if(v[x]) ans++;    ans=(ans+Mod)%Mod;    printf("%I64d\n",ans);    return 0;}
原创粉丝点击