linkios
給你一個長度爲$n$的數字串,其中$-1$的表示能夠填$1$~$k$中任意一個數,其他數的範圍也是從$1$~$k$。而對於連續$len$個數都不是相等的。問有多少種方案。數組
容易發現此題是一個計數類$dp$。咱們定義$f(i,j)$表示第$i$位選$j$的方案數,$ans[i]=\sum_{j=1}^k f(i,j)$。這時要有一個問題須要考慮,就是連續$len$個數不能重複,此時就要多定一個數組$del[u]$表示從當前位置以前數$len-1$個選$u$的方案數。就是爲後面的$dp$作準備。因此若如今位置爲$i$,則$del[u]=ans[i-len+1]-dp[i-len+1][u]$。而後$dp(i,j)$就爲$dp(i,j)=ans[i-1]-del[j]$。ide
#include<iostream> #include<cstring> #include<cstdio> #include<algorithm> #define int long long #define mod 998244353 using namespace std; inline int read(){ int f=1,ans=0;char c=getchar(); while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();} return f*ans; } const int N=100001; const int K=101; int dp[N][K],n,ans[N],cnt[K],del[K],a[N],k,len; signed main(){ n=read(),k=read(),len=read(); if(len==1){cout<<0;return 0;} for(int i=1;i<=n;i++) a[i]=read(); ans[0]=1; for(int i=1;i<=n;i++){ for(int j=1;j<=k;j++){ if(a[i]==j||a[i]==-1){ dp[i][j]=(ans[i-1]-del[j]+2*mod)%mod; cnt[j]++; if(cnt[j]>=len-1) del[j]=ans[i-len+1]-dp[i-len+1][j],del[j]=(del[j]+2*mod)%mod; ans[i]+=dp[i][j]; ans[i]%=mod; }else{ cnt[j]=0; del[j]=0; } } } printf("%I64d\n",ans[n]); }