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

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

#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");
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值