题面

题面

\(\Delta\)题面有点问题,应该是数列中没有长度大于等于\(len\)的连续数字才是合法的.

题解

设\(f[i][j]\)表示DP到\(i\)位,以\(j\)为结尾的方案数, \(sum[i]\)表示\(\sum_{j = 1}^{k}f[i][j]\), \(g[i][j]\)表示第\(i\)位为结尾,当前段全都是数字\(j\)的最长长度(不考虑\(len\)的限制,能延长就尽量延长,你可以理解为把\(1\)到\(i\)的\(-1\)全都改成\(j\),然后再看第\(i\)位以\(j\)为结尾的连续数字有多长)。

那么有:

\[f[i][j] = \begin{cases}
0 \quad s_i \ne -1 \ and \ s_i \ne j \\
sum[i - 1] \quad g[i][j] < len \\
sum[i - 1] - (sum[i - len] - f[i - len][j]) \quad others
\end{cases}\]

第一种转移比较简单,解释下最后两种。

第二种:

因为\(g[i][j] < len\),所以在第\(i\)位,以\(j\)结尾时,不管前面是什么情况,肯定都合法,所以直接加上上一位总的方案就可以了

第三种:(以下所说的连续数字含义均为连续相同数字)

先明确一点:对于一段长度大于等于\(len\)的连续数字而言,我们只会在它的第一个不合法位置减去它的方案数,例如一个长为\(len + k\)的连续数字,我们只会在它的第\(len\)位减去它的方案数。

显然这样可以保证不重不漏,也就相当于其实我们每次减去的都是以某个固定位置开头的不合法连续数字的方案数,所以肯定不会有重复和遗漏的。

那为什么不每次减去以某个固定位置结尾的不合法连续数字的方案数呢?

因为我们是从前向后DP的,所以对于前面一个固定位置的一些信息,我们已经处理出来了,对于以某个固定位置结尾的不合法连续数字而言,当我们DP到这个结尾位置的时候,这个地方的值正我们需要计算的,总不能自己调用自己吧。

再考虑计算:

首先\(sum[i - 1]\)是总的方案数,但是其中有一部分方案不合法,因为当前段长度大于等于\(len\).

因此我们再考虑如何计算不合法的方案。

根据我们的策略,对于一段长度大于等于\(len\)的连续数字,我们只会在它的第\(len\)位减去它的方案数。

也就是我们只能减去长度为\(len\)的连续数字

因此我们假定从第\(i\)位开始,向前\(len\)个都是\(j\).(注意此时\(g[i][j] >= len\),所以一定有方案可以使得从\(i\)向前\(len\)个都是\(j\))

那么因为已经不合法了,所以从第\(i - len\)位开始,往前走的就都可以任取,所以总方案数为\(sum[i - len]\).

但是我们只能统计长度为\(len\)的连续数字,所以第\(i - len\)位不能是\(j\),否则就会接在以前变成一段长度大于\(len\)的连续数字了。

因此我们还要减去以\(i - len\)为结尾的,结尾数字为\(j\)的方案数。

#include<bits/stdc++.h>
using namespace std;
#define R register int
#define p 998244353
#define AC 101000
#define ac 110 int n, k, len, ans;
int s[AC], f[AC][ac], g[AC][ac], sum[AC]; inline int read()
{
int x = 0;char c = getchar();bool zz = false;
while(c > '9' || c < '0') {if(c == '-') zz = true; c = getchar();}
while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return zz ? -x : x;
} inline void up(int &a, int b) {a += b; if(a < 0) a += p; if(a >= p) a-= p;}
inline int ad(int a, int b) {a += b; if(a < 0) a += p; if(a >= p) a -= p; return a;}
inline int mul(int a, int b) {return 1LL * a * b % p;} void pre()
{
n = read(), k = read(), len = read();
for(R i = 1; i <= n; i ++) s[i] = read();
} void work()
{
sum[0] = 1;
for(R i = 1; i <= n; i ++)
{
for(R j = 1; j <= k; j ++)
{
if(s[i] != -1 && s[i] != j) continue;
g[i][j] = ad(g[i - 1][j], (s[i] == -1 || s[i] == j));
if(g[i][j] < len) f[i][j] = sum[i - 1];
else up(f[i][j], ad(ad(sum[i - 1], -sum[i - len]), f[i - len][j]));
up(sum[i], f[i][j]);
}
}
printf("%d\n", sum[n]);
} int main()
{
freopen("in.in", "r", stdin);
pre();
work();
fclose(stdin);
return 0;
}

CF1093F Vasya and Array DP的更多相关文章

  1. Educational Codeforces Round 56 (Rated for Div. 2) F - Vasya and Array dp好题

    F - Vasya and Array dp[ i ][ j ] 表示用了前 i 个数字并且最后一个数字是 j 的方案数. dp[ i ][ j ] = sumdp [i - 1 ][ j ], 这样 ...

  2. CF1093F Vasya and Array

    题目链接:洛谷 以后还是要多打CF,不然就会错过这些很好的思维题了.我dp学得还是太烂,要多总结. 首先$len=1$就直接输出0. 我们考虑$dp[i][j]$表示前$i$个数的答案,而且第$i$个 ...

  3. CodeForces - 1093F:Vasya and Array (DP&计数)

    题意:N,K,L,以及给定长度为N的序列,表示其对应的颜色,-1表示还没有涂色,现在让你去涂色,使得最后没有大于等于L的连续的同色的情况. 思路:我们用dp[i][j]表示第i个位置颜色为j的合法方案 ...

  4. HDU 5653 Bomber Man wants to bomb an Array. dp

    Bomber Man wants to bomb an Array. 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5653 Description ...

  5. 江苏 徐州邀请赛 icpc B Array dp 滚动数组模板

    题目 题目描述 JSZKC is the captain of the lala team. There are N girls in the lala team. And their height ...

  6. URAL 1353 Milliard Vasya's Function(DP)

    题目链接 题意 : 让你找出1到10^9中和为s的数有多少个. 思路 : 自己没想出来,看的题解,学长的题解报告 题解报告 //URAL 1353 #include <iostream> ...

  7. Codeforces 57C Array dp暴力找到规律

    主题链接:点击打开链接 的非增量程序首先,计算, 如果不增加的节目数量x, 非减少一些方案是x 答案就是 2*x - n 仅仅需求得x就可以. 能够先写个n3的dp,然后发现规律是 C(n-1, 2* ...

  8. ZOJ 3872 Beauty of Array DP 15年浙江省赛D题

    也是一道比赛时候没有写出来的题目,队友想到了解法不过最后匆匆忙忙没有 A 掉 What a pity... 题意:定义Beauty数是一个序列里所有不相同的数的和,求一个序列所有字序列的Beauty和 ...

  9. 152. Maximum Product Subarray (Array; DP)

    Find the contiguous subarray within an array (containing at least one number) which has the largest ...

随机推荐

  1. L012-linux系统文件属性知识深入详解小结

    L012-linux系统文件属性知识深入详解小结 最近的学习重点不在这上面,所以更新的比较慢,再加上母亲住院,感情问题,一系列吧,愿快点度过这黑色的4月份,希望我能在5月份阳光起来,加油! 回归正题 ...

  2. 我们一起学习WCF 第二篇WCF承载多个接口

    前言:现在王大叔养了大批猪,赚了很多钱.但是最近发现养鸡也可以赚很多钱,他就像扩展业务开始养鸡.又过两年他发现市场对狗的需求量很大,他开始养狗.那么他改怎么做呢,不可能去修改猪住的地方把鸭子和狗放里面 ...

  3. Zigbee系列(end device)

    End device设备分为睡眠和非睡眠两种(RxOnWhenIdle标记不同). 入网时的association请求,会使用这个标记. 共同特性 子节点多次发送数据失败(无回应),发送孤点扫描(re ...

  4. cookie,session傻傻分不清楚?

    做了这么多年测试,还是分不清什么是cookie,什么是session?很正常,很多初级开发工程师可能到现在都搞不清什么是session,cookie相对来说会简单很多. 下面这篇文章希望能够帮助大家分 ...

  5. IDEA 配置Junit4

    Junit4 主要用来执行java程序的单元测试: 1 安装junit4插件 因为我安装过了,没有安装的再输入框搜索,然后安装就行 2 选择默认使用Junit4 3 红框中的test去掉,变为“$en ...

  6. vim神器(学习笔记)

    #本文并非原创,属于本人学习中的记录笔记或是转存笔记,如果涉及到哪位高人的创作权益,敬请海涵! Vim 是一个上古神器,本篇文章主要持续总结使用 Vim 的过程中不得不了解的一些指令和注意事项,以及持 ...

  7. CsvHelper文档-5配置

    CsvHelper文档-5配置 CsvHelper库被设计成快速且简单易用,但是有时候默认的是设置不符合要求,需要你自己改变一些东西.所以csvHelper内置了很多自定义设置选项来改变读写行为.特别 ...

  8. libCurl 初步认识 - cur easy

    cur easy接口简洁明了,主接口4个,辅接口5个. 主接口 初始化 + 配参数 + 执行 + 销毁 初始化 CURL* curl_easy_init() 获得CURL句柄,返回值需要判空. 配参数 ...

  9. sqli-labs学习笔记 DAY2

    DAY2 sqli-labs lesson 2 手工注入 URL:http://localhost/sqli-labs-master/Less-2/ Parameter:id 注入点检测:id=2;– ...

  10. Java跨平台的实现原理

    不同操作系统支持的指令集有所差异,只要在不同操作系统上安装对应的jvm,jvm负责把Java字节码翻译成对应机器的二进制码,从而实现java语言的跨平台.