CF1989E Distance to Different 题解

CF1989E Distance to Different

好题。题目要求 \(b\) 数组的数量,但 \(b\) 数组难以直接计算,而 \(b\) 数组和 \(a\) 数组的映射关系并不明显。考虑分析 \(b\) 的性质,并映射到其他数组。

我们发现,\(b\) 数组与 \(a\) 数组中元素的具体数值无关,只与 \(a\) 数组中元素的不等关系有关。因此,我们考虑把 \(b\) 数组映射到一个反映 \(a\) 数组中元素的不等关系的数组。

\(c_i=[a_i\ne a_{i-1}]\),特别的,不难发现 \(c_1=0\)。考虑将 \(b\) 数组映射到 \(c\) 数组。题目中要求 \(k\) 个元素至少出现一次,所以至少有 \(k-1\)\(c_i\) 等于 \(1\)。若至少有 \(k-1\)\(c_i\) 等于 \(1\),则一定可以构造出一个 \(a\) 数组满足条件,每次不同时换新的元素即可。因此,这个 \(c\) 数组是可行的,对应的 \(b\) 数组也是可行的。

但是,\(b\) 数组和 \(c\) 数组并不是严格的双射关系。\(c=[1,0,1]\)\(c=[1,1,1]\) 时,\(b\) 数组均为 \([1,1,1]\)。因此,我们需要强制舍去其中一种情况以保证双射。由于至少有 \(k\)\(c_i\) 等于 \(1\),显然应该舍去 \([1,0,1]\),这样可以获得更多的 \(c_i=1\),否则可能无法满足条件。

最后,我们使用动态规划计算满足条件的 \(c\) 数组数量。设状态 \(f[i][j][k][l]\) 表示第 \(i\) 个位置,前 \(1\) 位为 \(j\),这一位为 \(k\),一共出现 \(l\)\(c_i=1\) 的情况,显然有如下转移方程:

\[f[i][j][0][l]=f[i][j][0][l]+f[i-1][p][j][l] \]

\[f[i][j][1][l]=f[i][j][1][l]+f[i-1][p][j][l-1](p\ne1\lor j\ne0) \]

初始 \(f[1][0][0][0]=1\),目标 \(\sum_{i=0}^{1}\sum_{j=0}^{1}f[n][i][j][k-1]\)

时间复杂度 \(O(nk)\),代码中采用了另一种转移方式。

#include <bits/stdc++.h>
using namespace std;
long long k,n,f[200001][2][2][11],ans=0;
const long long mod=998244353;
int main()
{
    scanf("%lld%lld",&n,&k);
    f[1][0][0][0]=1;
    for(int i=2;i<=n;i++)
        for(int j=0;j<=1;j++)
            for(int l=0;l<=1;l++)
                for(int p=0;p<=k-1;p++)
                    for(int q=0;q<=1;q++)
                        {
                        if(j==1&&l==0&&q==1)continue;
                        if(p+q>=k)f[i][l][q][k-1]+=f[i-1][j][l][p],f[i][l][q][k-1]%=mod;
                        else f[i][l][q][p+q]+=f[i-1][j][l][p],f[i][l][q][p+q]%=mod;
                        }
    for(int i=0;i<=1;i++)
        for(int j=0;j<=1;j++)
            ans+=f[n][i][j][k-1],ans%=mod;
    printf("%lld\n",ans);
	return 0;
} 
posted @ 2025-02-17 16:06  w9095  阅读(8)  评论(0)    收藏  举报