计数做题记录

\(\text{Problems}\)

\(\text{Problem}1\text{ LG}11487\text{ (Blue)}\)

给定正整数 \(n,m\) 和一个长度为 \(n+m\)\(\texttt{01}\)\(S\)
对于 \(\texttt{01}\)\(T\),定义 \(f(T)\)\(S\) 最长的前缀的长度,使得该前缀是 \(T\) 的子序列。
对于每个恰有 \(n\)\(1\)\(m\)\(0\)\(\texttt{01}\)\(T\),求 \(\displaystyle\left(\sum f(T)\right)\bmod 2933256077\),该模数为质数。

保证 \(1\le n,m\le3\times10^6\)
\(\text{Time Limit }1\text{s},\text{Memory Limit }512\text{MB}\)

$\text{Hints}$
$\text{Hint}1$

考虑求出 \(\displaystyle g(k)=\sum[f(T)=k]\)

$\text{Hint}2$

发现 \(f(T)=k\),当且仅当 \(T\) 能表示为以下形式:

\[\overline{S_1\cdots S_1}S_1\overline{S_2\cdots S_2}S_2\cdots\overline{S_k\cdots S_k}S_k\overline{S_{k+1}\cdots S_{k+1}} \]

其中取反的部分长度可以为 \(0\)

$\text{Tutorial}$

请先阅读 \(\text{Hints}\)


设当前要求 \(g(k),k<n+m\)

\(\displaystyle cnt_0=\sum [S_k=\texttt{0}],cnt_1=\sum [S_k=\texttt{1}]\)
定义 \(\operatorname{place}(n,m)\) 为把 \(n\) 个无标号物体放进 \(m\) 个无标号盒子内,并允许有空盒子。
显然有

\[\operatorname{place}(n,m)=\begin{cases} 1,&n=m=0\\ \displaystyle\binom{n+m-1}{m-1},&n,m>0\\ 0,&\text{otherwise} \end{cases}\]

\(\text{Hint}2\),可得:

\[g(k)=\begin{cases} \operatorname{place}(m-cnt_0,cnt_1)\times\operatorname{place}(n-cnt_1,cnt_0+1),&S_{k+1}=\texttt{0}\\ \operatorname{place}(n-cnt_1,cnt_0)\times\operatorname{place}(m-cnt_0,cnt_1+1),&S_{k+1}=\texttt{1}\\ \end{cases}\]

特别的,\(g(n+m)=(n+m)[cnt_1=n\land cnt_0=m]\)

显然有 \(\displaystyle ans=\left(\sum_{i=1}^{n+m}i\times g(i)\right)\bmod 2933256077\)

预处理组合数后计算每个 \(g(k)\) 都是 \(O(1)\) 的。

时间复杂度 \(O(n+m)-O(n+m)\),空间复杂度 \(O(n+m)\)

$\text{Solution}$
#define forUp(i,a,b) for(int i=(a);i<=(b);++i)
#define forUP(i,a,b) for(int i=(a);i<(b);++i)
using int64=long long;
constexpr int N=6e6+10;int64 mod=2933256077;
int n,m;string s;
int64 fac[N],inv[N];
void init(int n=N-10){
	fac[0]=fac[1]=inv[0]=inv[1]=1;
	forUp(i,2,n)fac[i]=fac[i-1]*i%mod,inv[i]=(mod-mod/i)*inv[mod%i]%mod;
	forUp(i,3,n)inv[i]=inv[i-1]*inv[i]%mod;
}
int64 C(int n,int m){
	if(n<m||m<0)return 0;
	return fac[n]*inv[m]%mod*inv[n-m]%mod;
}
int64 place(int n,int m){
	if(n==0&&m==0)return 1;
	return C(n+m-1,m-1);
}
int cnt0,cnt1;int64 ans;
void solve(){
	init();
	cin>>n>>m>>s;s=" "+s;
	forUP(k,1,n+m){
		cnt0+=s[k]=='0',cnt1+=s[k]=='1';
		if(s[k+1]=='0')(ans+=place(m-cnt0,cnt1)*place(n-cnt1,cnt0+1)%mod*k)%=mod;
		if(s[k+1]=='1')(ans+=place(n-cnt1,cnt0)*place(m-cnt0,cnt1+1)%mod*k)%=mod;
	}
	cnt0+=s[n+m]=='0',cnt1+=s[n+m]=='1';
	if(cnt0==m&&cnt1==n)(ans+=n+m)%=mod;
	cout<<ans;
}
posted @ 2025-11-03 07:40  LXcjh4998  阅读(2)  评论(0)    收藏  举报