【XSY3955】作曲家(概率dp,生成函数,kmp)

题面

作曲家

题解

这种序列相似的见过很多次,但一直不会做,今天终于知道一个套路了。

\(s\)\(t\) 相似为 \(s\sim t\)。显然这个 “相似” 是有传递性的,即若 \(a\sim c\)\(b\sim c\),那么 \(a\sim b\)

前置知识/定义

概率相关的定义

定义 \(\overline{A}\) 表示事件 “事件 \(A\) 不发生”。

定义 \(P(A)\) 表示事件 \(A\) 发生的概率。

定义 \(P(A|B)\) 表示在事件 \(B\) 发生的前提下(即钦定 \(B\) 已经发生率),事件 \(A\) 发生的概率。

形状序列

定义一个序列 \(s\)形状序列为另一个长度也为 \(|s|\) 的序列 \(t\),满足对于 \(1\leq i\leq |s|\)

  • \(s_i\)\(s[1,i-1]\) 中没有出现过,那么 \(t_i=0\)
  • 否则,找到 \(s_i\)\(s[1,i-1]\) 中最后一次出现的位置,记作 \(j\),那么 \(t_i=i-j\)

\(s\) 的形状序列为 \(\operatorname{shape}(s)\),那么 \(s\sim t \iff \operatorname{shape}(s)=\operatorname{shape}(t)\)

合法形状序列

定义 \(n_0(t)\) 表示序列 \(t\)\(0\) 的个数。

定义合法序列为一个序列 \(s\),满足 \(s\) 中的每一个数在数集 \([1,n]\cap \mathbb{Z}\) 内。

对于一个序列 \(t\) 来说,如果 \(t\) 能成为某个合法序列的形状序列,那么称 \(t\)合法形状序列

容易知道整数序列 \(t\) 是合法形状序列当且仅当以下三个条件成立:(下面的 \(n\) 和本题中的 \(n\) 定义一样,为数集大小)

  • \(n_0(t)\leq n\)。即 \(t\) 中的不同的数的个数不能超过数集大小。
  • \(\forall 1\leq i\leq |t|\),若 \(t_i\neq 0\),有 \(1\leq i-t_i<i\)
  • \(\forall 1\leq i<j\leq|t|\),若 \(t_i,t_j\neq 0\),有 \(i-t_i\neq j-t_j\)

任意序列的形状序列都是合法形状序列。

对于一个合法形状序列 \(t\) 来说,考虑 \(t\) 可能是多少种不同序列的形状序列,易知 \(t\) 可能是 \(A_n^{n_0(t)}\) 种不同序列的形状序列。

子形状序列

对于一个合法形状序列 \(t\) 和整数 \(1\leq \ell\leq r\leq |t|\) 来说,定义 \(t\) 关于区间 \([l,r]\) 的子形状序列为一个长度为 \(r-l+1\) 的序列 \(t'\),满足对于所有的 \(1\leq i\leq r-l+1\)(令 \(j=l+i-1\))有:

\[t_i'= \begin{cases} 0&\text{if }j-t_j<l\\ t_j&\text{if }j-t_j\geq l\\ \end{cases} \]

把合法形状序列 \(t\) 关于区间 \([l,r]\) 的子形状序列记作 \(\operatorname{subshape}(t,l,r)\)

\(s\) 的形状序列为 \(t\),容易发现 \(\operatorname{subshape}(t,l,r)=\operatorname{shape}(s[l,r])\)

本题的分析

首先为了方便,记 \(\hat{a}=\operatorname{shape}(a)\)

首先注意到至少要先生成 \(m\) 次,所以不妨设生成了 \(m+k\) 次的概率为 \(p_k\),那么答案即为 \(ans=m+\sum\limits_{k=0}^{\infty}k\cdot p_k\)

将题目要求作一个等价转化:即使宣告生成停止,仍然可以继续生成(但之后不能再宣告生成停止了),可得一无限随机序列 \(S\),现在我们求的就是 “宣告停止时间” 的期望。

接下来我们会记录一个数组 \(q\)

首先,记连续生成 \(m\) 次随机数所得序列与 \(a\) 相似的概率为 \(q_m\),那么 \(q_m=n^{-m}A_n^{n_0(\hat{a})}\)

定义:

  • 事件 \(A_k\)\(S[k+1,k+m]\sim a\)。那么 \(\forall i\geq 0,P(A_i)=q_m\)

  • 事件 \(B_k\)\(m+k\) 为宣告停止时间。那么 \(p_k=P(B_k)\)

显然 \(p_k=P(B_k)=P(A_k\cap \overline{B_0}\cap \overline{B_1}\cap \cdots\cap \overline{B_{k-1}})\)

又由于事件 \(B_i\) 是互斥的,所以:

\[\begin{aligned} p_k&=P(A_k\cap\overline{B_0}\cap \overline{B_1}\cap \cdots\cap \overline{B_{k-1}})\\ &=P(A_k)-\sum_{i=0}^{k-1}P(A_k\cap B_i)\\ &=q_m-\sum_{i=0}^{k-1}P(B_i)P(A_k|B_i)\\ &=q_m-\sum_{i=0}^{k-1}p_iP(A_k|B_i) \end{aligned} \]

接下来只需计算 \(P(A_k|B_i)\)

  • \(i\leq k-m\) 时,事件 \(A_k\) 与事件 \(B_i\) 相互独立,所以 \(P(A_k|B_i)=P(A_k)=q_m\)

  • \(k-m<i<k\) 时,设 \(\ell=k-i\)

    下面说的东西要自己画图理解。

    一方面,由于我们钦定了 \(B_i\) 成立,所以 \(S[i+1,i+m]\sim a[1,m]\),所以 \(S[i+\ell+1,i+m]\sim a[\ell+1,m]\),即 \(S[k+1,i+m]\sim a[\ell+1,m]\)

    另一方面,如果 \(A_k\) 成立,就有 \(S[k+1,k+m]\sim a[1,m]\),所以 \(S[k+1,k+m-\ell]\sim a[1,m-\ell]\),即 \(S[k+1,i+m]\sim a[1,m-\ell]\)

    又由相似的传递性可知 \(a[\ell+1,m]\sim a[1,m-\ell]\)

    所以在 \(B_i\) 发生的前提下,\(A_k\) 发生的必要条件是 \(a[\ell+1,m]\sim a[1,m-\ell]\)。所以若 \(a[\ell+1,m]\not\sim a[1,m-\ell]\),恒有 \(P(A_k|B_{i})=0\)。发现这只与 \(\ell\) 有关,所以此时记 \(P(A_k|B_i)=q_{\ell}=0\)

    接下来考虑 \(a[1,m-\ell]\sim a[\ell+1,m]\) 成立的情况,可得 \(\operatorname{subshape}(\hat{a},1,m-\ell)=\operatorname{subshape}(\hat{a},\ell+1,m)\)

    注意到 \(\operatorname{subshape}(\hat{a},1,m-\ell)=\hat{a}[1,m-\ell]\),所以可得 \(\hat{a}[1,m-\ell]=\operatorname{subshape}(\hat{a},\ell+1,m)\)

    又由于我们刚刚由 \(B_i\) 成立的前提得到了 \(S[k+1,i+m]\sim a[\ell+1,m]\),所以又可得 \(\hat{a}[1,m-\ell]=\operatorname{shape}(S[k+1,i+m])=\operatorname{shape}(S[k+1,k+m-\ell])\)

    现在我们着眼 \(T[1,m]=S[k+1,k+m]\),那么要解决的就是这么一个问题:我们现在已经有了 \(a[1,m-\ell]\sim T[1,m-\ell]\),那么当 \(T[m-\ell+1,m]\) 的每个数都在 \(1\sim n\) 里面随机生成时,最后 \(a[1,m]\sim T[1,m]\) 的概率是多少?

    为计算概率,可以逐项确定序列。当 \(\hat{a}_i\neq 0\) 时,该项被唯一确定,所以对概率贡献一个因子 \(n^{-1}\);当 \(\hat{a}_i=0\) 时,该项可以从之前未出现的字符中任取,所以对概率贡献的因子是 \(n^{-1}(n - n_0(\hat{a}[1, i - 1]))\)。综合起来,概率为 \(n^{-\ell}A_{n-n_0(\hat{a}[1,m-\ell])}^{n_0(\hat{a}[m-\ell+1,m])}\),也是一个只和 \(\ell\) 有关的量,记为 \(q_{\ell}\)

综上所述,可以列式:

\[\begin{aligned} &q_m=n^{-m}A_n^{n_0(\hat{a})}\\ \\ &q_{\ell}= \begin{cases} n^{-\ell}A_{n-n_0(\hat{a}[1,m-\ell])}^{n_0(\hat{a}[m-\ell+1,m])}&\text{if }a[1,m-\ell]\sim a[\ell+1,m]\\ 0&\text{if }a[1,m-\ell]\not\sim a[\ell+1,m]\\ \end{cases}\\ \end{aligned} \]

那么:

\[p_k=q_m-\sum_{i=0}^{k-1}p_iP(A_k|B_i)=q_m-\sum_{i=0}^{k-m}q_mp_i-\sum_{\ell=1}^{\min(k,m-1)}q_{\ell}p_{k-\ell} \]

移项:

\[p_k+\sum_{\ell=1}^{\min(k,m-1)}q_{\ell}p_{k-\ell}+\sum_{i=0}^{k-m}q_mp_i=q_m \]

往生成函数的方向靠:

\[p_kx^k+\sum_{\ell=1}^{\min(k,m-1)}q_{\ell}x^{\ell}p_{k-\ell}x^{k-\ell}+\sum_{i=0}^{k-m}q_mx^{k-i}p_ix^i=q_mx^{k} \]

\(P(x)\)\(p_k\) 的生成函数(即 \(P(x)=p_0+p_1x+p_2x^2+\cdots\)),那么有:

\[P(x)+\sum_{\ell=1}^{m-1}q_{\ell}x^{\ell}P(x)+\frac{q_mx^m}{1-x}P(x)=\frac{q_m}{1-x} \]

(注意 \(\sum\limits_{\ell=1}^{\min(k,m-1)}q_{\ell}x^{\ell}p_{k-\ell}x^{k-\ell}\)\(\ell\) 的上界设为 \(\min(k,m-1)\) 是为了防止越界,但写成生成函数的形式后就不用担心越界的问题了)

(注意 \(\sum\limits_{i=0}^{k-m}q_mx^{k-i}p_ix^i\)\(i\) 的取值范围是 \([0,k-m]\),所以 \(k-i\) 的取值范围是 \([m,k]\)

提公因式:

\[P(x)\left(1+\sum_{\ell=1}^{m-1}q_{\ell}x^{\ell}+\frac{q_mx^m}{1-x}\right)=\frac{q_m}{1-x} \]

\(P(x)=Q^{-1}(x)\),那么:

\[Q(x)=\dfrac{1+\sum\limits_{\ell=1}^{m-1}q_{\ell}x^{\ell}+\dfrac{q_mx^m}{1-x}}{\dfrac{q_m}{1-x}}=x^m+\frac{1-x}{q_m}\left(1+\sum\limits_{\ell=1}^{m-1}q_{\ell}x^{\ell}\right) \]

注意到若一多项式 \(f(x)=\sum\limits_{i\geq 0}a_ix^i\),有 \(f'(x)=\sum\limits_{i\geq 1}a_iix^{i-1}\)。(多项式求导)

所以答案为:

\[\begin{aligned} ans&=m+\sum_{k=0}^{\infty}k\cdot p_k\\ &=m+\sum_{k=1}^{\infty}k\cdot p_k\\ &=m+\sum_{k=1}^{\infty}k\cdot p_k\cdot 1^{k-1}\\ &=m+P'(1)\\ &=m+\left[\dfrac{1}{Q(1)}\right]' \end{aligned} \]

引理:若 \(f(x),g(x)\) 为多项式,那么 \(\left[\dfrac{g(x)}{f(x)}\right]'=-\dfrac{f'(x)g(x)+f(x)g'(x)}{f^2(x)}\)。(见高中选修2-2,以下有关导数的知识或引理的证明也请参见这本书或自行上网搜索,本文不再阐述太多)

那么有 \(\left[\dfrac{1}{Q(x)}\right]'=-\dfrac{Q'(x)}{Q^2(x)}\)

发现当 \(x=1\) 时,\(Q(1)=1\),所以 \(\left[\dfrac{1}{Q(1)}\right]'=-\dfrac{Q'(1)}{Q^2(1)}=-Q'(1)\)

于是现在的问题是求 \(Q'(1)\)

\[\begin{aligned} Q'(x)&=\left[x^m+\frac{1-x}{q_m}\left(1+\sum\limits_{\ell=1}^{m-1}q_{\ell}x^{\ell}\right)\right]'\\ &=\left[x^m\right]'+\left[\frac{1-x}{q_m}\left(1+\sum\limits_{\ell=1}^{m-1}q_{\ell}x^{\ell}\right)\right]'\\ &=mx^{m-1}+\left[\frac{1-x}{q_m}\left(1+\sum\limits_{\ell=1}^{m-1}q_{\ell}x^{\ell}\right)\right]' \end{aligned} \]

\(x=1\) 时,\(mx^{m-1}=m\)。那么现在的问题是求出 \(\left[\dfrac{1-x}{q_m}\left(1+\sum\limits_{\ell=1}^{m-1}q_{\ell}x^{\ell}\right)\right]'\)

引理:若 \(f(x),g(x)\) 为多项式,那么 \(\big[f(x)g(x)\big]'=f'(x)g(x)+f(x)g'(x)\)

不妨设 \(f(x)=\dfrac{1-x}{q_m}\)\(g(x)=\left(1+\sum\limits_{\ell=1}^{m-1}q_{\ell}x^{\ell}\right)\),注意到当 \(x=1\)\(f(1)=0\),所以 \(\big[f(1)g(1)\big]'=f'(1)g(1)+f(1)g'(1)=f'(1)g(1)\)

\(f'(x)=\left(\dfrac{1-x}{q_m}\right)'=-\dfrac{1}{q_m}\),所以 \(f'(1)g(1)=-\dfrac{1}{q_m}g(1)=-\dfrac{1}{q_m}\left(1+\sum\limits_{\ell=1}^{m-1}q_{\ell}\right)\)

所以 \(Q'(1)=m-\dfrac{1}{q_m}\left(1+\sum\limits_{\ell=1}^{m-1}q_{\ell}\right)\)

所以 \(ans=m+\left[\dfrac{1}{Q(1)}\right]'=m-Q'(1)=\dfrac{1}{q_m}\left(1+\sum\limits_{\ell=1}^{m-1}q_{\ell}\right)\)

\(a[1,m]\) 的所有相似前后缀的长度集合为 \(L_m=\{1\leq k\leq m\ |\ a[1,k]\sim a[m-k+1,m]\}\),注意这里 \(k\) 的范围是可以到 \(m\) 的。

然后暴力把 \(q_m\)\(q_{\ell}\) 的定义式代入,得到:

\[ans=\frac{1}{n!}\sum_{k\in L_m}n^k(n-n_0(a[1,k]))! \]

那么现在只需要求 \(L_m\)

下面说的东西也要自己画图理解。

注意到,若 \(k,\ell \in L\)\(k>\ell\),那么 \(a[1,\ell] \sim a[m-\ell+1,m]\sim a[k-\ell +1,k]\),也就是说 \(a[1,\ell]\)\(a[k-\ell+1,k]\) 也是 \(a[1,k]\) 的一对相似前后缀。

那么不妨设 \(L_r=\{1\leq k\leq r\ |\ a[1,k]\sim a[r-k+1,r]\}\) 表示 \(a[1,r]\) 的所有相似前后缀的长度集合,\(b_r\)\(L_r\) 集合内除了 \(r\) 以外最大的那个数。那么 \(\forall 1\leq i< b_r\)\(i\) 也在集合 \(L_r\) 内的充要条件是 \(i\) 也在集合 \(L_{b_r}\) 内。

那么我们从 \(r=m\) 开始,不断递归 \(r\gets b_r\),那么遍历到的所有的 \(r\) 就是 \(L_m\) 内所有的数。

那么现在的问题是如何对于每一个 \(1\leq r\leq m\) 求出 \(b_r\)

发现 \(b_r\) 的定义和 kmp 数组的定义很像,所以直接用类似 kmp 的方法求出所有的 \(b_r\) 即可。

听说这道题推导路线十分经典,但我见都没见过类似的题(((

代码如下:

#include<bits/stdc++.h>

#define N 1000010

using namespace std;

namespace modular
{
	const int mod=998244353;
	inline int add(int x,int y){return x+y>=mod?x+y-mod:x+y;}
	inline int dec(int x,int y){return x-y<0?x-y+mod:x-y;}
	inline int mul(int x,int y){return 1ll*x*y%mod;}
}using namespace modular;

inline int read()
{
	int x=0,f=1;
	char ch=getchar();
	while(ch<'0'||ch>'9')
	{
		if(ch=='-') f=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9')
	{
		x=(x<<1)+(x<<3)+(ch^'0');
		ch=getchar();
	}
	return x*f;
}

inline int poww(int a,int b)
{
	int ans=1;
	while(b)
	{
		if(b&1) ans=mul(ans,a);
		a=mul(a,a);
		b>>=1;
	}
	return ans;
}

int n,m,a[N],shape[N];
int last[N],n0[N];
int fac[N],pown[N];
int b[N];

vector<int>L;

bool check(int j,int i)
{
	return shape[j]==(shape[i]>j?0:shape[i]);
}

int main()
{
	n=read(),m=read();
	for(int i=1;i<=m;i++)
	{
		a[i]=read();
		n0[i]=n0[i-1];
		if(!last[a[i]]) n0[i]++;
		else shape[i]=i-last[a[i]]+1;
		last[a[i]]=i;
	}
	b[1]=0;
	for(int i=2,j=0;i<=m;i++)
	{
		while(j&&!check(j+1,i)) j=b[j];
		if(check(j+1,i)) j++;
		b[i]=j;
	}
	int j=m;
	while(j)
	{
		L.push_back(j);
		j=b[j];
	}
	pown[0]=fac[0]=1;
	for(int i=1;i<=n;i++) fac[i]=mul(fac[i-1],i);
	for(int i=1;i<=m;i++) pown[i]=mul(pown[i-1],n);
	int ans=0;
	for(int i=0,size=L.size();i<size;i++)
	{
		int k=L[i];
		ans=add(ans,mul(pown[k],fac[n-n0[k]]));
	}
	printf("%d\n",mul(ans,poww(fac[n],mod-2)));
	return 0;
}
/*
10 2
1 1
*/
posted @ 2022-10-30 14:26  ez_lcw  阅读(19)  评论(0编辑  收藏  举报