CodeForces 1093F Vasya and Array
阿新 • • 發佈:2020-08-08
題意
給一個長度為 \(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]); }