Codeforces Educational Codeforces Round 56 (Rated for Div. 2) 1093F. Vasya and Array

版权声明:希望大家转载的时候把公式转载好一点QAQ,我就公式打得很辛苦了... https://blog.csdn.net/Myriad_Dreamin/article/details/85037516

有一个长度为 n n 的的数列, a i a_i 的值域只有 k k 个元素。
一个数列有一些数字已经填上。现在要求数列连续的数字长度不能超过 l l ,问所有不同的数列的个数有多少个。
1.考虑所有的数字都没填上。设 d p [ i ] [ j ] [ s ] dp[i][j][s] 为第 i i 个位置填入第 j j 种颜色且已经有连续的 s s 个数字的方案数。显然:
那么:
d p [ i ] [ j ] [ s ] = d p [ i 1 ] [ j ] [ s 1 ] [ s l 1 ] ( p = 1 ( t = 1 k d p [ i l + 1 ] [ t ] [ p ] d p [ i l + 1 ] [ j ] [ p ] ) ) , 2 s l 1 , d p [ i ] [ j ] [ s ] = 1 t k , j t p = 1 d p [ i 1 ] [ t ] [ p ] , s = 1 d p [ i ] [ j ] [ s ] = 0 , s l . 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.
求和得:
p = 1 s d p [ i ] [ j ] [ p ] = p = 1 t = 1 k d p [ i 1 ] [ j ] [ p ] [ s l 1 ] ( p = 1 t = 1 k d p [ i l + 1 ] [ t ] [ p ] p = 1 d p [ i l + 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])
因为具有规整性,并且考虑到 d p [ i ] [ j ] [ s ] = d p [ i 1 ] [ j ] [ s 1 ] dp[i][j][s]=dp[i-1][j][s-1]
所以令 a v a [ i ] [ j ] = p = 1 d p [ i ] [ j ] [ p ] , s u m [ i ] = i = 1 k a v a [ i ] [ j ] \displaystyle ava[i][j]=\sum_{p=1}^{\infty}dp[i][j][p],sum[i]=\sum_{i=1}^k ava[i][j] ,得:
a v a [ i ] [ j ] = s u m [ i 1 ] [ max a v a l e n j l 1 ] ( s u m [ i l + 1 ] a v a [ i l + 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
其中 max a v a l e n j \max avalen_j 是指当前可能达到的最大连续后缀长度。
2.考虑有的数字已经填上。显然这时候,如果 j = a [ i ] j=a[i] ,则可以继续转移,但是只有一种可能。如果 j a [ i ] j\neq a[i] ,也可以继续转移,但是 max a v a l e n j \max avalen_j 被隔断,所以重新计算。

#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[i]-=mod;
            }else{
                len[j]=bad[j]=0;
            }
        }
    }
    printf("%I64d\n",dp[n]);
    //std::system("pause");
}

猜你喜欢

转载自blog.csdn.net/Myriad_Dreamin/article/details/85037516