有一个长度为nnn的的数列,aia_iai的值域只有kkk个元素。
一个数列有一些数字已经填上。现在要求数列连续的数字长度不能超过lll,问所有不同的数列的个数有多少个。
1.考虑所有的数字都没填上。设dp[i][j][s]dp[i][j][s]dp[i][j][s]为第iii个位置填入第jjj种颜色且已经有连续的sss个数字的方案数。显然:
那么:
dp[i][j][s]=dp[i1][j][s1][sl1](p=1(t=1kdp[il+1][t][p]dp[il+1][j][p])),2sl1,dp[i][j][s]=1tk,jtp=1dp[i1][t][p],s=1dp[i][j][s]=0,sl. dp[i][j][s]=dp[i-1][j][s-1] -[s\\geqslant l-1](\\sum_{p=1}^{\\infty}(\\sum_{t=1}^k dp[i-l+1][t][p]-dp[i-l+1][j][p])),2\\leqslant s \\leqslant l-1,\\\\ dp[i][j][s]=\\sum_{1\\leqslant t\\leqslant k,j\\neq t}\\sum_{p=1}^{\\infty}dp[i-1][t][p],s=1\\\\ dp[i][j][s]=0,s\\geqslant l. dp[i][j][s]=dp[i1][j][s1][sl1](p=1(t=1kdp[il+1][t][p]dp[il+1][j][p])),2sl1,dp[i][j][s]=1tk,j̸=tp=1dp[i1][t][p],s=1dp[i][j][s]=0,sl.
求和得:
p=1sdp[i][j][p]=p=1t=1kdp[i1][j][p][sl1](p=1t=1kdp[il+1][t][p]p=1dp[il+1][j][p]) \\sum_{p=1}^{s}dp[i][j][p]=\\sum_{p=1}^{\\infty}\\sum_{t=1}^kdp[i-1][j][p]-[s\\geqslant l-1](\\sum_{p=1}^{\\infty}\\sum_{t=1}^k dp[i-l+1][t][p]-\\sum_{p=1}^{\\infty}dp[i-l+1][j][p]) p=1sdp[i][j][p]=p=1t=1kdp[i1][j][p][sl1](p=1t=1kdp[il+1][t][p]p=1dp[il+1][j][p])
因为具有规整性,并且考虑到dp[i][j][s]=dp[i1][j][s1]dp[i][j][s]=dp[i-1][j][s-1]dp[i][j][s]=dp[i1][j][s1]
所以令ava[i][j]=p=1dp[i][j][p],sum[i]=i=1kava[i][j]\\displaystyle ava[i][j]=\\sum_{p=1}^{\\infty}dp[i][j][p],sum[i]=\\sum_{i=1}^k ava[i][j]ava[i][j]=p=1dp[i][j][p],sum[i]=i=1kava[i][j],得:
ava[i][j]=sum[i1][maxavalenjl1](sum[il+1]ava[il+1]),i=1,2,,n ava[i][j]=sum[i-1]-[\\max avalen_j\\geqslant l-1](sum[i-l+1]-ava[i-l+1]),i=1,2,\\dots,n ava[i][j]=sum[i1][maxavalenjl1](sum[il+1]ava[il+1]),i=1,2,,n
其中maxavalenj\\max avalen_jmaxavalenj是指当前可能达到的最大连续后缀长度。
2.考虑有的数字已经填上。显然这时候,如果j=a[i]j=a[i]j=a[i],则可以继续转移,但是只有一种可能。如果ja[i]j\\neq a[i]j̸=a[i],也可以继续转移,但是maxavalenj\\max avalen_jmaxavalenj被隔断,所以重新计算。

#include <cstdio>
#include <iostream>
const int N=100005,K=105;
const long long mod=998244353LL;
int a[N];
long long dp[N],ava[N][K],len[K],bad[K];
int main(){
    int n,k,l;
    scanf(\"%d%d%d\",&n,&k,&l);l--;
    if(!l){
        puts(\"0\");
        return 0;
    }
    for(int i=1;i<=n;i++){
        scanf(\"%d\",&a[i]);
    }
    dp[0]=1;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=k;j++){
            if(a[i]==j||a[i]==-1){
                ava[i][j]=(dp[i-1]+mod-bad[j])%mod;
                len[j]++;
                if(len[j]>=l){
                    bad[j]=(dp[i-l]+mod-ava[i-l][j])%mod;
                }
                dp[i]+=ava[i][j];
                if(dp[i]>=mod)dp

					
				
收藏 打印
您的足迹: