[CF1093F]Vasya and Array

link

题目大意

给你一个长度为$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]$。

#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]);
}
View Code

 

转载于:https://www.cnblogs.com/si-rui-yang/p/10133215.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值