Gym 101490K Safe Racing (dp转换, 超超超级详细,包你看懂)
题意:给你一个长为L的圆形跑道,让你放置警示牌,相邻两个警示牌相隔距离不能超过S,让你求有多少种方案数放置。数据L,S都是1e6。
来个例子:L = 13, S = 5。一个圈表示长度为1。
思路:因为是一个圈,我们必须得判断最后一个牌子和第一个牌子的相距距离,所以如果我们规定了第一个放在那,最后一个放在那,这道题就简单多了。比如这个。
第一步思考:
1 当我们第一个放在1号位子时,我们最后一个能放的位置有12,13,14,15,16。
2 当我们第一个放在2号位子时,我们最后一个能放的位置有13,14,15,16。
3 当我们第一个放在3号位子时,我们最后一个能放的位置有14,15,16。
4 当我们第一个放在4号位子时,我们最后一个能放的位置有15,16。
5 当我们第一个放在5号位子时,我们最后一个能放的位置只有16。
6 当我们第一个放在6号位子时,不行,因为最大不能相差6,如果放在了6,我们得在1到5之间放置一个警示牌,和前面的情况已经重复了。

第二步思考:
确定了第一个位子和最后一个位子,你只需要确定中间能放置的种类不久行了吗?然后你想一会会发现这不就是求一个直行跑道放警示牌能放多少种吗?最多不能相隔s,你刚开始做dp时,每次上台阶你只能上1或者2阶,n阶的楼梯你可以走的方案数有多少种?这个题不就是你每次可以走1~S阶,求走n阶的方案数么?你的dp[i]表示的就是长度为i,在第i这个地方放置一个牌子的方案数。 所以dp[i]就等于dp[i-1]+dp[i-2]....+dp[i-s+1]啊。这不就写出来了吗?
需要注意的是,长度为三的,是有4个点,因为0可以放。

正常写是这样
dp[0] = 1;
for(int i = 1; i <= l; i++){
for(int j = i-1; j >= max(0, i-s); j--){
(dp[i] += dp[j]) %= mod;
}
}
但是复杂度肯定说不过去,再一想你想要的只不过要维护一个长为s的区间和而已,所以直接记录前s个的前缀和,然后每次加一个是,减去你维护的区间第一个值就行了。
dp[0] = now = 1;
for(int i = 1; i <= l; i++){
dp[i] = now;
(now += dp[i]) %= mod;
if(i >= s){ //维护长度为s的区间和。
now = (now - dp[i-s] + mod) % mod;
}
}
还记得第一步吗?

我们要的答案就是这些的对应位置的dp值相加。

就变成了:
1 当我们第一个放在1号位子时,我们最后一个能放的方案数有dp[11] + dp[12] + dp[13] + dp[14] + dp[15]
2 当我们第一个放在2号位子时,我们最后一个能放的方案数有dp[11] + dp[12] + dp[13] + dp[14]
3 当我们第一个放在3号位子时,我们最后一个能放的方案数有dp[11] + dp[12] + dp[13]
4 当我们第一个放在4号位子时,我们最后一个能放的方案数有dp[11] + dp[12]
5 当我们第一个放在5号位子时,我们最后一个能放的方案数有dp[11]
再开一个数组记录dp的前缀和就能直接算了。
这题就a了。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const ll mod = 123456789;
const int maxn = 1e6 + 5;
ll dp[maxn], sum[maxn];
int main(){
ll l, s;
cin >> l >> s;
ll now = 1;
dp[0] = 1;
sum[0] = 1;
for(int i = 1; i <= l; i++){
dp[i] = now;
sum[i] = (sum[i-1]+dp[i]) % mod; // 前缀和
(now += dp[i]) %= mod;
if(i >= s){
now = (now - dp[i-s] + mod) % mod;
}
}
ll ans = 0;
for(int i = 1; i <= s; i++){
ans = (ans + sum[l-i] - sum[l-s-1] + mod)%mod;
}
cout << ans << endl;
return 0;
}
Gym 101490K Safe Racing (dp转换, 超超超级详细,包你看懂)的更多相关文章
- 问题 L: 超超的中等意思
问题 L: 超超的中等意思 时间限制: 1 Sec 内存限制: 128 MB提交: 366 解决: 27[提交] [状态] [命题人:jsu_admin] 题目描述 已知p,q,k和一个难搞得多项 ...
- 问题 F: 超超的自闭意思
问题 F: 超超的自闭意思 时间限制: 1 Sec 内存限制: 128 MB提交: 80 解决: 10[提交] [状态] [命题人:jsu_admin] 题目描述 质数定义为在大于1的自然数中,除 ...
- (原创)超详细一步一步在eclipse中配置Struts2环境,无基础也能看懂
(原创)超详细一步一步在eclipse中配置Struts2环境,无基础也能看懂 1. 在官网https://struts.apache.org下载Struts2,建议下载2.3系列版本.从图中可以看出 ...
- 利用树莓派来安装opencv从而来调动摄像头工作(没有坑,超超自己试过)
超超最近参加了学校里一位特别厉害的老师讲的课(两天,我就从一个小白然后了解了树莓派以及Arduino这些我之前都没有了解过的东西,由于结课的需要,我们需要自己设计一个创意以及完成作品)所以才有了这篇文 ...
- 水题 Gym 100553K Knockout Racing
题目传送门 /* 题意:有若干个点在一个区间内来回移动,1m/s. 水题:n^2的复杂度能解决,注意时间可能大于一个周期,要取模 */ #include <cstdio> #include ...
- UVA - 825Walking on the Safe Side(dp)
id=19217">称号: UVA - 825Walking on the Safe Side(dp) 题目大意:给出一个n * m的矩阵.起点是1 * 1,终点是n * m.这个矩阵 ...
- 对于挑战书上的很久之前都看不懂的DP看懂的突破
突破一..牢记问题概念 并且牢记dp状态方程 突破二..一直有一个求和dp转化成O1dp递推的式子看不懂.. 看不懂的原因是..没有分清求和符号作用的范围 提醒:以后遇到求和符号一定明确其求和的式子的 ...
- 小学生都能看懂的数位dp
前言 数位dp其实很久前就知道了,也做过几道和其他算法混在一起的题目,其实通过手玩是能做的 但毕竟是种算法,还是系统学下比较好(节省手玩时间) 模板题 P2602 [ZJOI2010]数字计数 化简题 ...
- JS 时间处理(GMT转换,超24小时加一天,时间差计算)
计算天数,加小时,加分数 Date.prototype.Format = function (fmt) { // author: meizz var o = { "M+": thi ...
- Codeforces Gym 100231L Intervals 数位DP
Intervals 题目连接: http://codeforces.com/gym/100231/attachments Description Start with an integer, N0, ...
随机推荐
- OSS管理文件(Node.js)
let OSS = require('ali-oss'); let config = { region: 'oss-cn-hangzhou', //你的Region 注意 这个只要 空间名 不要 ht ...
- pg_freespacemap查看表膨胀
pg_freespacemap模块提供一种检查自由空间映射(FSM)的手段.它提供一个名为pg_freespace的函数,或精确的说是两个重载函数.该函数在一个给定的页面或关系中的所有页面的自由空间映 ...
- Alfred 好用工具分享
好用的mac工具分享 1.带历史记录的剪切板 根据快捷键切换选择保存的数据 2.创建热键工作流程 将常用的工具变为热键,快捷切换 如何创建: 设置热键 单击右键 创建actions 打开app 然后将 ...
- zk api连接超时问题 org.apache.zookeeper.KeeperException$ConnectionLossException: KeeperErrorCode = ConnectionLoss for
遇到 org.apache.zookeeper.KeeperException$ConnectionLossException: KeeperErrorCode = ConnectionLoss fo ...
- 通过Jsoup,爬取车辆品牌,车系,LOGO等
@Test public void test4() throws IOException { for (int i = 65; i <= 90; i++) { String value = St ...
- vue后台管理系统——订单管理模块
电商后台管理系统的功能--订单管理模块 1. 订单管理概述 订单管理模块用于维护商品的订单信息, 可以查看订单的商品信息.物流信息,并且可以根据实际的运营情况对订单做适当的调整. 2. 订单列表 在c ...
- 使用git钩子防止合并分支
git是一款实用的版本管理工具,我们通过git init初始化一个git仓库,git会在当前目录为我们生成一个.git/目录,用来管理我们的版本文件信息. 在这个目录中有一个二级目录.git/hook ...
- 【PTA】1049 Counting Ones
The task is simple: given any positive integer N, you are supposed to count the total number of 1's ...
- 量化交易——MACD是什么,用python来验证交易时把它作为买卖信号到底靠不靠谱
在我刚开始学习股票的时候,是跟着b站上的视频学习的,当讲到macd的时候,up主反复强调macd是指标之王,股票里面有那么多的指标,但是却只有macd被称为指标之王,当macd出现金叉的时候,预示着股 ...
- 十大经典排序之快速排序(C++实现)
快速排序 通过一趟排序将待排序列分割成两部分,其中一部分记录的关键字均比另一部分记录的关键字小.之后分别对这两部分记录继续进行排序,以达到整个序列有序的目的. 思路: (1)选择基准:从数列中挑出一个 ...