• 题解 CF1093F 【Vasya and Array】


    考虑通过 (DP) 来解决本题。设 (f_{i,j}) 为考虑了前 (i) 个位置且第 (i) 个位置为数字 (j) 的方案数,(s_i)(sumlimits_{j=1}^k f_{i,j})(l_{i,j}) 为位置 (i) 往前都是数字 (j) 的最长长度,得:

    [large f_{i,j}= egin{cases} s_{i-1} &l_{i,j} < len\ \ s_{i-1}-s_{i-len}+f_{i-len,j} &l_{i,j} geqslant len\ end{cases} ]

    (l_{i,j} < len) 时不可能出现不合法的情况,所以直接从 (s_{i-1}) 转移过来。

    (l_{i,j} geqslant len) 时转移过来的状态就会出现不合法的情况。考虑对于区间 ([i-len+1,i]),若该区间都为 (j),就会出现不合法的情况,因为区间都为 (j) 只有一种情况,所以其方案数即为 (s_{i-len})。但是这里是想把长度恰好为 (len) 且在 (i) 结尾的不合法情况减去,直接减去 (s_{i-len}) 会多减长度大于 (len) 的情况,所以还要加上 (f_{i-len,j})

    #include<bits/stdc++.h>
    #define maxn 100010
    #define maxk 110
    #define p 998244353
    using namespace std;
    typedef long long ll;
    template<typename T> inline void read(T &x)
    {
        x=0;char c=getchar();bool flag=false;
        while(!isdigit(c)){if(c=='-')flag=true;c=getchar();}
        while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
        if(flag)x=-x;
    }
    int n,k,len;
    ll a[maxn],f[maxn][maxk],s[maxn],l[maxn][maxk];
    int main()
    {
        read(n),read(k),read(len);
        for(int i=1;i<=n;++i) read(a[i]);
        for(int i=1;i<=n;++i)
            for(int j=1;j<=k;++j)
                if(a[i]==j||a[i]==-1)
                    l[i][j]=l[i-1][j]+1;
        s[0]=1;
        for(int i=1;i<=n;++i)
        {
            for(int j=1;j<=k;++j)
            {
                if(a[i]!=j&&a[i]!=-1) continue;
                f[i][j]=s[i-1];
                if(l[i][j]>=len) f[i][j]=((f[i][j]-s[i-len]+p)%p+f[i-len][j])%p;
                s[i]=(s[i]+f[i][j])%p;
            }
        }
        printf("%lld",s[n]);
        return 0;
    }
    
  • 相关阅读:
    Django框架基础之序列化
    资产采集
    CMDB
    数据库--三层架构
    Django 项目一补充
    评论楼
    图片预览
    验证码
    如何使用C/C++动态库与静态库中的宏
    Matlab 直线方程、采样函数
  • 原文地址:https://www.cnblogs.com/lhm-/p/13518458.html
Copyright © 2020-2023  润新知