CF585F Digits of Number Pi

发布时间 2023-10-15 14:15:07作者: WrongAnswer_90

CF585F Digits of Number Pi

更好的阅读体验

观察数据范围,考虑数位 DP。

首先把长串中 \(len\geq\lfloor \frac{d}{2}\rfloor\) 的串提出来,塞进一个 trie 里,然后建立 ACAM,然后直接 DP 就行了。

\(f_{i,j,0/1,0/1,0/1}\) 表示当前在 trie 图上走了 j 步到达了第 i 个节点,是否已经出现子串,是否满足低位限制,是否满足高位限制,枚举 \(k\) 表示第 \(j\) 个字符是什么,然后在 AC 自动机上跑。第三个 \(0/1\) 在走到一个结束点后就一定是 \(1\),第四个维度选了一个大于 \(x\) 串当前位的字符后变成 \(1\),第五个维度也是同理,细节比较多,但是实在是没有任何思维含量。详细的转移方程见代码。

inline void Madd(int&x,int y){x+y>=MOD?x=x+y-MOD:x=x+y;}
int n,d,ans,f[2][500001][2][2][2];
char s[1001],t1[1001],t2[1001];
namespace ACAM
{
	int end[500001],trie[500001][10],fail[500001],cnt=1;
	queue<int> q;
	inline void build()
	{
		for(int i=0;i<10;++i)trie[0][i]=1;
		for(int i=1;i+d/2-1<=n;++i)
		{
			int now=1;
			for(int j=i;j<=min(n,i+d/2-1);++j)
			{
				if(!trie[now][s[j]-'0'])trie[now][s[j]-'0']=++cnt;
				now=trie[now][s[j]-'0'];
				if(j>=i+d/2-1)end[now]=1;
			}
		}
		q.e(1);
		while(!q.empty())
		{
			int now=q.front();q.pop();
			for(int i=0;i<10;++i)
			{
				if(trie[now][i])fail[trie[now][i]]=trie[fail[now]][i],q.e(trie[now][i]);
				else trie[now][i]=trie[fail[now]][i];
			}
		}
	}
}
using namespace ACAM;
#define g f[pre][trie[i][k]]
#define nw f[now][i]
inline void mian()
{
	scanf("%s%s%s",s+1,t1+1,t2+1),ans=0,n=strlen(s+1),d=strlen(t1+1);
	for(int i=1;i<=d;++i)t1[i]-='0',t2[i]-='0';
	build(),f[1][1][0][0][0]=1;int now=0,pre=1;
	for(int j=0;j<d;++j)
	{
		now^=1,pre^=1,memset(f[pre],0,sizeof(f[pre]));
		for(int i=1;i<=cnt;++i)
		{
			for(int k=0;k<10;++k)
			{
				int is=end[trie[i][k]];
				if(k<t1[j+1])
				{
					if(k<t2[j+1])
					{
						Madd(g[is|0][1][1],nw[0][1][0]),Madd(g[is|0][1][1],nw[0][1][1]);
						Madd(g[is|1][1][1],nw[1][1][0]),Madd(g[is|1][1][1],nw[1][1][1]);
					}
					else if(k==t2[j+1])
					{
						Madd(g[is|0][1][0],nw[0][1][0]),Madd(g[is|0][1][1],nw[0][1][1]);
						Madd(g[is|1][1][0],nw[1][1][0]),Madd(g[is|1][1][1],nw[1][1][1]);
					}
					else
					{
						Madd(g[is|0][1][1],nw[0][1][1]),Madd(g[is|1][1][1],nw[1][1][1]);
					}
				}
				else if(k==t1[j+1])
				{
					if(k<t2[j+1])
					{
						Madd(g[is|0][0][1],nw[0][0][0]),Madd(g[is|0][0][1],nw[0][0][1]);
						Madd(g[is|0][1][1],nw[0][1][0]),Madd(g[is|0][1][1],nw[0][1][1]);
						Madd(g[is|1][0][1],nw[1][0][0]),Madd(g[is|1][0][1],nw[1][0][1]);
						Madd(g[is|1][1][1],nw[1][1][0]),Madd(g[is|1][1][1],nw[1][1][1]);
					}
					else if(k==t2[j+1])
					{
						Madd(g[is|0][0][0],nw[0][0][0]),Madd(g[is|0][0][1],nw[0][0][1]);
						Madd(g[is|0][1][0],nw[0][1][0]),Madd(g[is|0][1][1],nw[0][1][1]);
						Madd(g[is|1][0][0],nw[1][0][0]),Madd(g[is|1][0][1],nw[1][0][1]);
						Madd(g[is|1][1][0],nw[1][1][0]),Madd(g[is|1][1][1],nw[1][1][1]);
					}
					else
					{
						Madd(g[is|0][0][1],nw[0][0][1]),Madd(g[is|0][1][1],nw[0][1][1]);
						Madd(g[is|1][0][1],nw[1][0][1]),Madd(g[is|1][1][1],nw[1][1][1]);
					}
				}
				else
				{
					if(k<t2[j+1])
					{
						Madd(g[is|0][1][1],nw[0][0][0]),Madd(g[is|0][1][1],nw[0][0][1]);
						Madd(g[is|0][1][1],nw[0][1][0]),Madd(g[is|0][1][1],nw[0][1][1]);
						Madd(g[is|1][1][1],nw[1][0][0]),Madd(g[is|1][1][1],nw[1][0][1]);
						Madd(g[is|1][1][1],nw[1][1][0]),Madd(g[is|1][1][1],nw[1][1][1]);
					}
					else if(k==t2[j+1])
					{
						Madd(g[is|0][1][0],nw[0][0][0]),Madd(g[is|0][1][0],nw[0][1][0]);
						Madd(g[is|0][1][1],nw[0][0][1]),Madd(g[is|0][1][1],nw[0][1][1]);
						Madd(g[is|1][1][0],nw[1][0][0]),Madd(g[is|1][1][0],nw[1][1][0]);
						Madd(g[is|1][1][1],nw[1][0][1]),Madd(g[is|1][1][1],nw[1][1][1]);
					}
					else
					{
						Madd(g[is|0][1][1],nw[0][0][1]),Madd(g[is|0][1][1],nw[0][1][1]);
						Madd(g[is|1][1][1],nw[1][0][1]),Madd(g[is|1][1][1],nw[1][1][1]);
					}
				}
			}
		}
	}
	for(int i=1;i<=cnt;++i)
	{
		Madd(ans,f[pre][i][1][0][0]),Madd(ans,f[pre][i][1][0][1]);
		Madd(ans,f[pre][i][1][1][0]),Madd(ans,f[pre][i][1][1][1]);
	}
	write(ans);
}