abc433F - 1122 Subsequence 2题解

这道题一上来并没有什么思路。

但是看到了1122这个样例,再加上数字很少,就想着对于每两个数字组合,拆贡献。

设一个子序列为

\[\underbrace{111\dots1 }_{(n-1)个1}\ 1\ \underbrace{222\dots2}_{m个2}\]

考虑枚举需要用到1和2的个数k,那么它的合法方案数就为

\[\sum\limits_{k=1}^{min(n,m)}C_{n-1}^{k-1}C_m^k \]

但是枚举要 \(O(n)\) ,每次统计个数要 \(O(n)\),总体时间 \(O(n^2)\) ,爆炸了。。。

再观察一下这个式子,是不是和卷积特别像?

然后就尝试往卷积上想。

开始推式子:

\[\begin{aligned} \sum\limits_{k=1}^{min(n,m)}C_{n-1}^{k-1}C_m^k &=\sum\limits_{k=1}^{min(n,m)}C_{n-1}^{n-1-(k-1)}C_m^k\\ &=\sum\limits_{k=1}^{min(n,m)}C_{n-1}^{n-k}C_m^k\\ &=C_{n+m-1}^{n} \end{aligned} \]

答案就出来了。

时间复杂度: \(O(n)\) 。

最后附上代码:

#include<bits/stdc++.h>
#define int long long
#define qy(FILE) freopen(FILE".in","r",stdin);freopen(FILE".out","w",stdout);
using namespace std;
const int N=1e6+5,INF=0x3f3f3f3f3f3f3f3f,mod=998244353;
string s;
int qian[N][12],hou[N][12],n;
int power(int a,int b)
{
	int res=1;
	a=a%mod;
	while(b)
	{
		if(b&1) res=res*a%mod;
		a=a*a%mod;
		b/=2;
	}
	return res%mod;
}
int jie[N],jie_ni[N];
void init()
{
	jie[0]=1;
	for(int i=1;i<=N-5;i++)
		jie[i]=jie[i-1]*i%mod;
	jie_ni[N-5]=power(jie[N-5],mod-2);
	for(int i=N-5;i>0;i--)
		jie_ni[i-1]=jie_ni[i]*i%mod; 
}
int C(int x,int y)
{
	if(x<y||y<0||y<0)return 0;
	return jie[x]*jie_ni[y]%mod*jie_ni[x-y]%mod;
}
signed main()
{
//	qy("q");
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	init();
	cin>>s;
    n=s.size();
    s=' '+s;
    for(int i=1;i<=n;i++)
    	for(int j=0;j<10;j++)
    		qian[i][j]=qian[i-1][j]+(j==s[i]-'0');
    for(int i=n;i>=1;i--)
    	for(int j=0;j<10;j++)
   			hou[i][j]=hou[i+1][j]+(j==s[i]-'0');
    int ans=0;
    for(int i=1;i<=n;i++)
    {
        if(s[i]=='9') continue;
        int x=qian[i][s[i]-'0'];
        int y=hou[i][s[i]-'0'+1];
        if(x==0||y==0) continue;
        ans=(ans+C(x+y-1,x))%mod;
    }
    cout<<ans<<'\n';
	return 0;
}
posted on 2026-10-19 18:36  hemingxi_2030  阅读(2)  评论(0)    收藏  举报