[USACO19JAN]Train Tracking 2 P
拿到本题后,可以观察到一个性质,如果出现了 \(c_i \ne c_{i + 1}\) 那么我们一定可以确定一个位置的值,这启示着我们将 \(c_i\) 相同的部分单独拿出来考虑再将最后的答案合并。于是可以先思考一个更为特殊的问题,所有 \(c_i\) 都相同的答案。为了让所有区间都被满足填了一个 \(c_i\),可以令 \(dp_i\) 表示前 \(i\) 个区间都存在一个 \(c_i\) 的方案。但你发现这是不好转移的,因为你不知道这个区间的 \(1\) 填在哪里,而且这个 \(1\) 填的位置可能对后面的区间造成影响,因此这样是不行的。先解决不满足后效性的问题,为了让当前的选择不会对后面产生影响,我们只能每次填在当前区间的最前面,但你可以发现因为区间每次只向右挪了一位,所以每次填在区间最前面是可以覆盖前 \(n - k + 1\) 个位置的答案的。因此这个想法是很有希望的,所以我们可以令 \(dp_i\) 表示当前填的 \(c_i\) 最后在 \(i\) 的方案,那么就有转移(\(m = 1e9 - c_i + 1\)):
\]
于此同时你可以发现 \(dp_{i - 1}\) 的转移中也会包含同样的 \(k - 1\) 个 \(dp\) 值,即:
\]
\]
则可也类似错位相消的方法把中间的值消去:
\]
拿 \(dp_i\) 与其做差可得:
\]
这样转移就可以做到 \(O(1)\) 了,总体 \(dp\) 的复杂度就是 \(O(n)\) 的了。最后统计答案时候同样枚举最后一个填 \(c_i\) 的位置,显然只能在 \([n - k + 1, n]\) 中,那么最后的答案就为:
\]
可以发现这就是 \(dp_{n + 1}\),于是我们就在 \(O(n)\) 的时间复杂度内解决了这个特殊问题。
再回来考虑原来的问题,将原来的 \(c\) 序列划分成很多由相同 \(c_i\) 组成的段。一个直接的想法就是将满足这一段相同 \(c_i\) 的段的方案(假设这一段相同 \(c_i\) 的长度为 \(len\),即用 \(c_i\) 去填长度为 \(len + k - 1\) 的段的方案)算出来再将所有段的答案相乘。但是你会发现段与段之间是会互相影响的,也就是说两端之间需要填的位置会有重复,貌似还是不好去计数,但仔细分析一下会有影响的部分部分会发现(假设当前段开头位置为 \(i\),最后一个位置为 \(j\)):
假如 \(c_{i - 1} > c_i\),则 \(i \sim i + k - 2\) 上填的数都要大于 \(c_{i - 1}\),我们何不将这部分的答案划给前一种 \(c_{i - 1}\) 来算呢?于此同时 \(i + k - 1\) 这个位置也以及确定必须填 \(c_i\),因此 \(i\) 能算的区间长度就要减去 \(k\)。
假如 \(c_{j + 1} > c_i\),则 \(j + 1 \sim j + k - 1\) 上填的数都要大于 \(c_{j + 1}\) 同理我们可以将这一段划分给 \(j + 1\) 来算,因此 \(i\) 能算的区间长度又要减去 \(k\)。
那么这样将 \(i\) 能算的答案算出来再将所有块的答案相乘即可,复杂度 \(O(n \log n)\)(\(\log\) 来自于计算 \((m - 1) ^ k\))。
#include<bits/stdc++.h>
using namespace std;
#define rep(i, l, r) for(int i = l; i <= r; ++i)
const int N = 100000 + 5;
const int inf = 1000000000;
const int Mod = 1000000000 + 7;
int n, k, P, ans, a[N], dp[N];
int read(){
char c; int x = 0, f = 1;
c = getchar();
while(c > '9' || c < '0'){ if(c == '-') f = -1; c = getchar();}
while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x * f;
}
int Inc(int a, int b){ return (a += b) >= Mod ? a - Mod : a;}
int Dec(int a, int b){ return (a -= b) < 0 ? a + Mod : a;}
int Mul(int a, int b){ return 1ll * a * b % Mod;}
int fpow(int a, int b){ int ans = 1; for(; b; a = Mul(a, a), b >>= 1) if(b & 1) ans = Mul(ans, a); return ans;}
int solve(int n, int m){
rep(i, 1, n + 1) dp[i] = 0;
dp[0] = dp[1] = 1, P = fpow(m - 1, k);
rep(i, 2, n + 1){
dp[i] = Mul(m, dp[i - 1]);
if(i - k > 0) dp[i] = Dec(dp[i], Mul(dp[i - k - 1], P));
}
return dp[n + 1];
}
int main(){
n = read(), k = read(), ans = 1;
rep(i, 1, n - k + 1) a[i] = read();
rep(i, 1, n - k + 1){
int j = i, len = 0; while(j <= n && a[j] == a[i]) ++j;
--j, len = j - i + k;
if(a[i - 1] > a[i]) len -= k;
if(a[j + 1] > a[i]) len -= k;
ans = Mul(ans, solve(len, inf - a[i] + 1));
i = j;
}
printf("%d", ans);
return 0;
}
[USACO19JAN]Train Tracking 2 P的更多相关文章
- P5204 [USACO19JAN]Train Tracking 2
P5204 [USACO19JAN]Train Tracking 2 毒毒题,对着嘤文题解看了贼久 首先考虑此题的一个弱化版本:如果输入的所有\(c_i\)相等怎么做 现在假设有\(len\)个数,取 ...
- [USACO19JAN]Train Tracking 2——神仙结论题+DP
原题链接 orz xzz巨佬 首先发现一个结论:两个相邻的\(c\)值如果不相同的话,就可以固定某个位置的值了 这启示我们把连续且相等的\(c\)给单独拿出来看,也就是对于一些\(c_i=c_{i+1 ...
- [luogu5204]Train Tracking 2
考虑一个位置的上界,即$bi=min(c_{i-k+1},c_{i-k+2},--,ci)$,那么每一个位置有两种方式:1.达到上界:2.未达到上界那么可以将权值相同的ci和bi提出来,由于权值不同的 ...
- [源码解析] 模型并行分布式训练Megatron (2) --- 整体架构
[源码解析] 模型并行分布式训练Megatron (2) --- 整体架构 目录 [源码解析] 模型并行分布式训练Megatron (2) --- 整体架构 0x00 摘要 0x01 启动 1.1 分 ...
- [TensorBoard] Train and Test accuracy simultaneous tracking
训练时的实时状态跟踪的重要性 不言而喻. [Tensorboard] Cookbook - Tensorboard 讲解调节更新频率 直接上代码展示: import numpy as np impo ...
- (转)CVPR 2016 Visual Tracking Paper Review
CVPR 2016 Visual Tracking Paper Review 本文摘自:http://blog.csdn.net/ben_ben_niao/article/details/52072 ...
- 论文笔记之:Fully-Convolutional Siamese Networks for Object Tracking
gansh Fully-Convolutional Siamese Network for Object Tracking 摘要:任意目标的跟踪问题通常是根据一个物体的外观来构建表观模型.虽然也取得了 ...
- 论文笔记之:Learning Multi-Domain Convolutional Neural Networks for Visual Tracking
Learning Multi-Domain Convolutional Neural Networks for Visual Tracking CVPR 2016 本文提出了一种新的CNN 框架来处理 ...
- 论文笔记:Learning Attribute-Specific Representations for Visual Tracking
Learning Attribute-Specific Representations for Visual Tracking AAAI-2019 Paper:http://faculty.ucmer ...
随机推荐
- 遍历 HashMap 的 5 种最佳方式
使用 Iterator 遍历 HashMap EntrySet 使用 Iterator 遍历 HashMap KeySet 使用 For-each 循环迭代 HashMap 使用 Lambda 表达式 ...
- FAT
目录 概 主要内容 代码 Zhang J., Xu X., Han B., Niu G., Cui L., Sugiyama M., Kankanhalli M. Attacks which do n ...
- [黑科技]pb_ds库(G++)
一.hash(速度快的恐怖).http://codevs.cn/problem/1230/ 1 #include<stdio.h> 2 #include<ext/pb_ds/asso ...
- 【计理01组03号】Java基础知识
简单数据类型的取值范围 byte:8 位,1 字节,最大数据存储量是 255,数值范围是 −128 ~ 127. short:16 位,2 字节,最大数据存储量是 65536,数值范围是 −32768 ...
- Vue.js高效前端开发 • 【Vue组件】
全部章节 >>>> 文章目录 一.Vue组件介绍 1.组件概述 2.组件使用步骤 3.实践练习 一.Vue组件使用 1.组件注册 2.组件注册语法糖 3.使用script或te ...
- Oracle 创建数据表以及对数据表、字段、主外键、约束的操作
选择主键的原则: 最少性 尽量选择使用单个键作为主键 稳定性 尽量选择数值更新少的列作为主键 1.创建数据表(CREATE TABLE) --创建数据表Student create table Stu ...
- Ranger知识地图
自己总结的Ranger的学习路线和知识点, 提供给感兴趣的同学入门参考之用. Ranger入门路线 1.准备能够上网的电脑,Eclisp开发环境,Linux服务器等: 2.掌握Hadoop(HDFS/ ...
- Zookeeper集群安装(开启kerberos)
安装规划 zookeeper集群模式,安装到如下三台机器 10.43.159.237 zdh-237 10.43.159.238 zdh-238 10.43.159.239 zdh-239 Kerbe ...
- VUE3 之 键盘事件
1. 概述 老话说的好:宁愿自己吃亏,也不让他人吃亏. 言归正传,今天我们来聊聊 VUE3 的 键盘事件. 2. 键盘事件 2.1 敲击任意键触发事件 <body> <div id= ...
- RPC框架下实现文件上传到linux服务器
一.前端使用element -ui 的upload组件 :data 表示额外传递的参数, :header 表示设置请求头参数,如,token等, action表示后台api接口的地址 二. conto ...