1. 程式人生 > 實用技巧 >CodeForces 1093F Vasya and Array

CodeForces 1093F Vasya and Array

題意

給一個長度為 \(n\) 的整數序列 \(a\),其中 \(a_i\) 要麼為 \(-1\),要麼為 \(1\sim k\) 中的整數。

求出將所有 \(-1\) 替換為 \(1\sim k\) 中整數的方案數,滿足替換後的序列中不存在連續 \(l\) 個相同的數,對 \(998244353\) 取模。

\(\texttt{Data Range:}1\leq l\leq n\leq 10^5,1\leq k\leq 100\)

題解

注意到 \(k\) 的範圍很小,可以設一個 \(f_{i,j}\) 表示第 \(i\) 個位置的數字為 \(j\) 的時候字首的方案數,再記一個 \(s_i=\sum f_{i,j}\)

首先注意到只有 \(a_i=-1\) 或者 \(a_i=j\) 的時候 \(f_{i,j}\) 才可能被轉移到。

於是考慮設 \(len_{i,j}\) 表示以 \(i\) 為字尾最多連續的 \(j\) 的個數。

\(len_{i,j}<l\) 的時候 \(f_{i,j}=s_{i-1}\)

否則因為可以在這段字尾中填出大於等於 \(l\) 的,要減掉不合法的方案數,為 \(s_{i-l}-f_{i-l,j}\)

程式碼

#include<bits/stdc++.h>
using namespace std;
typedef int ll;
typedef long long int li;
const ll MAXN=2e5+51,MOD=998244353;
ll n,kk,l,p;
ll x[MAXN],f[MAXN][101],len[MAXN][101],s[MAXN];
inline ll read()
{
    register ll num=0,neg=1;
    register char ch=getchar();
    while(!isdigit(ch)&&ch!='-')
    {
        ch=getchar();
    }
    if(ch=='-')
    {
        neg=-1;
        ch=getchar();
    }
    while(isdigit(ch))
    {
        num=(num<<3)+(num<<1)+(ch-'0');
        ch=getchar();
    }
    return num*neg;
}
int main()
{
    n=read(),kk=read(),l=read(),s[0]=1;
    if(l==1)
    {
        return puts("0"),0;
    }
    for(register int i=1;i<=n;i++)
    {
        x[i]=read();
        for(register int j=1;j<=kk;j++)
        {
            len[i][j]=len[i-1][j]+(x[i]==-1||x[i]==j);
        }
    }
    if(x[1]==-1)
    {
        for(register int i=1;i<=kk;i++)
        {
            f[1][i]=1;
        }
        s[1]=kk;
    }
    else
    {
        f[1][x[1]]=1,s[1]=1;
    }
    for(register int i=2;i<=n;i++)
    {
        for(register int j=1;j<=kk;j++)
        {
            if(x[i]==-1||x[i]==j)
            {
                f[i][j]=s[i-1];
                if(i>=l)
                {
                    p=i-l;
                    if(len[i][j]-len[p][j]==l)
                    {
                        f[i][j]=((li)f[i][j]+f[p][j]-s[p]+MOD)%MOD;
                    }
                }
            }
            s[i]=(s[i]+f[i][j])%MOD;
        }
    }
    printf("%d\n",s[n]);
}