題意:
給出一段長度爲 n 的整數序列,一個正整數 k ,一個正整數 len ,序列中的所有數均在 1 ~k 之間,或者等於 −1。
如果沒有長度大於 len 的連續相同數字則該數段是好的。
可以將 -1 改爲 1 ~k 之間的整數,將該數列變爲好的,求出方案數,對 998244353 取模。
思路:
F[i][j]表示第i個位置填數字j的方案數。
S[i]表示填完前i個位置的方案數
如果第i爲j或者-1,則第i位可以爲j :F[i][j]=s[i-1]
但是會有重複的情況:#@¥@#¥@XXXX(len個X)
怎麼把這種情況刪除,首先一點len區間的數要麼就是X或者-1纔會出現上面的情況。
重複的個數是s[i-len]-f[i-len][j],在i-len的位置上除了填j外另外的所有可以結尾的數字都可以加上一段X得到狀態f[i][j]
#include<iostream>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<cstdio>
#include<algorithm>
#include<string>
#include<map>
#include<queue>
#include<vector>
#include<stack>
#define ll long long
#define maxn 4001000
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int P=998244353;
int n,k,len,cnt[101000][110],f[101000][110],s[101000],a[101000];
ll rd()
{
ll x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
void init()
{
n=rd();k=rd();len=rd();
rep(i,1,n) a[i]=rd();
s[0]=1;
rep(i,1,k)
rep(j,1,n)
cnt[j][i]=cnt[j-1][i]+(a[j]==i||a[j]==-1?1:0);
}
void work()
{
memset(f,0,sizeof(f));
rep(i,1,n)
{
rep(j,1,k)
{
if(a[i]!=-1&&a[i]!=j) continue;
f[i][j]=s[i-1];
if(i>=len&&cnt[i][j]-cnt[i-len][j]==len)
{
f[i][j]=(f[i][j]-s[i-len]+f[i-len][j])%P;
f[i][j]=(f[i][j]+P)%P;
}
}
rep(j,1,k)
s[i]=(s[i]+f[i][j])%P;
}
printf("%d\n",s[n]);
}
int main()
{
init();
work();
}