zoukankan      html  css  js  c++  java
  • CF585F. Digits of Number Pi

    题目大意

    题解

    裸题

    建SAM,在SAM上面数位dp维护位置和当前长度即可

    注意要先枚举新加的数,然后统一跳fail直到可以往下接,否则时间不能保证

    时间复杂度O(10*nd^2)

    code

    #include <bits/stdc++.h>
    #define fo(a,b,c) for (a=b; a<=c; a++)
    #define fd(a,b,c) for (a=b; a>=c; a--)
    #define add(a,b) a=((a)+(b))%1000000007
    #define mod 1000000007
    #define ll long long
    //#define file
    using namespace std;
    
    int a[51],b[2011],tr[2011][10],fa[2011],Len[2011],n,d,D,i,j,k,l,I,J,K,L,s,len,tot;
    char S[1001],s1[51],s2[51];
    ll ans,f[51][2011][26][2],F[2011][26][2];
    namespace G{
    	int a[2011][2],ls[2011],len;
    	void New(int x,int y) {++len;a[len][0]=y;a[len][1]=ls[x];ls[x]=len;}
    	void dfs(int t)
    	{
    		int i;
    		b[++tot]=t;
    		for (i=ls[t]; i; i=a[i][1])
    		dfs(a[i][0]);
    	}
    };
    
    void copy(int t1,int t2) {memcpy(tr[t1],tr[t2],sizeof(tr[t2]));}
    void New(int t,int x) {++len;if (tr[t][x]) copy(len,tr[t][x]);tr[t][x]=len;Len[len]=Len[t]+1;}
    void build()
    {
    	len=l=1;
    	fo(i,1,n)
    	{
    		New(l,S[i]-'0'),j=fa[l];
    		while (j && !tr[j][S[i]-'0']) tr[j][S[i]-'0']=len,j=fa[j];
    		
    		if (!j) fa[len]=1;
    		else
    		if (Len[j]+1==Len[tr[j][S[i]-'0']]) fa[len]=tr[j][S[i]-'0'];
    		else
    		{
    			k=tr[j][S[i]-'0'],New(j,S[i]-'0');
    			fa[len]=fa[k],fa[len-1]=fa[k]=len;
    			j=fa[j];
    			while (tr[j][S[i]-'0']==k) tr[j][S[i]-'0']=len,j=fa[j];
    		}
    		l=tr[l][S[i]-'0'];
    	}
    	
    	fo(i,2,len) G::New(fa[i],i);
    	G::dfs(1);
    }
    
    void dp(char st[51],int S)
    {
    	fo(i,1,d) a[i]=st[i]-'0';
    	memset(f,0,sizeof(f));
    	fo(s,1,a[1])
    	if (tr[1][s])
    	++f[1][tr[1][s]][1][s<a[1]]; else ++f[1][1][0][s<a[1]];
    	fo(i,2,d)
    	{
    		fo(s,1,9)
    		if (tr[1][s])
    		++f[i][tr[1][s]][1][1]; else ++f[i][1][0][1];
    	}
    	
    	fo(i,1,d-1)
    	{
    		I=i+1;
    		fo(s,0,9)
    		{
    			memcpy(F,f[i],sizeof(F));
    			fd(j,len,2)
    			{
    				fo(k,0,D)
    				{
    					fo(l,0,1)
    					if (!tr[b[j]][s])
    					{
    						if (k<D)
    						add(F[fa[b[j]]][Len[fa[b[j]]]][l],F[b[j]][k][l]);
    						else
    						add(F[fa[b[j]]][D][l],F[b[j]][k][l]);
    						F[b[j]][k][l]=0;
    					}
    				}
    			}
    			
    			fo(j,1,len)
    			{
    				if (tr[j][s])
    				J=tr[j][s]; else J=j;
    				
    				fo(k,0,D)
    				{
    					if (k<D)
    					K=k+(tr[j][s]>0);else K=D;
    					
    					fo(l,0,1)
    					if (l || s<=a[i+1])
    					{
    						L=(s<a[i+1])?1:l;
    						add(f[I][J][K][L],F[j][k][l]);
    					}
    				}
    			}
    		}
    	}
    	
    	fo(j,1,len)
    	{
    		if (S==-1)
    		add(ans,-f[d][j][D][1]);
    		else
    		add(ans,f[d][j][D][0]+f[d][j][D][1]);
    	}
    }
    
    int main()
    {
    	#ifdef file
    	freopen("CF585F.in","r",stdin);
    	#endif
    	
    	scanf("%s",S+1);n=strlen(S+1);
    	scanf("%s",s1+1);
    	scanf("%s",s2+1);
    	d=strlen(s1+1),D=d/2;
    	
    	build();
    	dp(s1,-1),dp(s2,1);
    	printf("%lld
    ",(ans+mod)%mod);
    	
    	fclose(stdin);
    	fclose(stdout);
    	return 0;
    }
    
  • 相关阅读:
    新人,请多指教,有个java小问题: bety a=300,强制类型转换,分析我的做法是否正确?谢谢
    生活健康
    小涛涛
    学习笔记(三)
    学习笔记(二)
    学习笔记(一)
    子元素宽度为100%,缩小窗口,父元素出现横向滚动条,滚动条向右拉,父元素右边有一块空白区域,没有背景颜色
    word-wrap:break-word和word-break:break-all的区别
    链接link使用href=“#”和href="##"的区别
    C#中在路径前使用 @ 的作用
  • 原文地址:https://www.cnblogs.com/gmh77/p/13658809.html
Copyright © 2011-2022 走看看