【LuoguP5004】 专心OI - 跳房子
首先这是一道计数类DP,那我们得先推式子,经过瞎掰乱凑,经过认真分析,我们可以得到这样的方程
F(N)=F(0)+F(1)+....+F(N-M-1)
所有F初值为1,F(1)=2
ANS=F(N+M);
那显然我们有这样的代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
const int M=1e9+;
using namespace std;
inline int read(){
char chr=getchar(); int f=,ans=;
while(!isdigit(chr)) {if(chr=='-') f=-;chr=getchar();}
while(isdigit(chr)) {ans=(ans<<)+(ans<<);ans+=chr-'';chr=getchar();}
return ans*f;
}
void write(int x){
if(x<) putchar('-'),x=-x;
if(x>) write(x/);
putchar(x%+'');
}int n,m,f[];
int main(){
n=read(),m=read();
f[]=;f[]=;
for(int i=;i<=n+m;i++){
f[i]=;
for(int j=;j<=i-m-;j++)
if(f[i]+f[j]>M) f[i]=f[i]+f[j]-M;
else f[i]=f[i]+f[j];//卡一波时间
}cout<<f[n+m];
return ;
}
显然这是O(n^2)的算法,然而面对N=1e18,这个算法可以去优化见鬼了,这样子由于语句比较简单,勉强可以过十万的数据大概30分
考虑优化:
我们先看一下上面的式子,尝试对这个式子变形...好吧,其实就是迭代,然后用鸽笼原理一通乱搞:
F(N)=F(N-1)+F(N-M-1)
ANS=F(N)
好了我们把这个东西优化得到了O(N)的算法:
期望得分:50pts
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
const int M=1e9+;
using namespace std;
inline int read(){
char chr=getchar(); int f=,ans=;
while(!isdigit(chr)) {if(chr=='-') f=-;chr=getchar();}
while(isdigit(chr)) {ans=(ans<<)+(ans<<);ans+=chr-'';chr=getchar();}
return ans*f;
}
void write(int x){
if(x<) putchar('-'),x=-x;
if(x>) write(x/);
putchar(x%+'');
}int n,m,f[];
int main(){
n=read(),m=read();
f[]=;f[]=;
for(int i=;i<=n;i++)
f[i]=(f[i-]+f[max(i-m-,)])%M;
cout<<f[n];
return ;
}
考虑继续优化
某个大佬说过1e18的数据考虑logn的算法,比如快速幂。
这既然是DP,那自然往矩阵乘法考虑。
考虑构造矩阵:m这么小,而且递推式中出现的常量只有m,显然矩阵的大小要往m*m考虑
m=1的时候斐波那契,显然不用我推了
看一下其他情况:

得到通式(写了的是1,其他是0):

然后会矩阵加速的同学都知道该怎么做了吧...
// luogu-judger-enable-o2
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define int long long
const int M=1e9+;
using namespace std;
inline int read(){
char chr=getchar(); int f=,ans=;
while(!isdigit(chr)) {if(chr=='-') f=-;chr=getchar();}
while(isdigit(chr)) {ans=(ans<<)+(ans<<);ans+=chr-'';chr=getchar();}
return ans*f;
}
void write(int x){
if(x<) putchar('-'),x=-x;
if(x>) write(x/);
putchar(x%+'');
}int n,m;
struct P{int a[][];P(){memset(a,,sizeof(a));}}A,B;
P operator *(const P &x,const P &y){
P ans;
for(int i=;i<m;i++)
for(int k=;k<m;k++)
for(int j=;j<m;j++)
ans.a[i][j]=(ans.a[i][j]+x.a[i][k]*y.a[k][j])%M;
return ans;
}
void KSM(int n){
while(n){
if(n&) B=B*A;
n>>=;A=A*A;
}
}
inline void init(){
n=read(),m=read();--n,++m;
A.a[m-][m-]=A.a[][m-]=;
for(int i=;i<m-;i++) A.a[i+][i]=;//初始矩阵
for(int i=;i<m;i++)B.a[][i]=i+;
}
signed main(){
init();KSM(n);
write(B.a[][]);
return ;
}
【LuoguP5004】 专心OI - 跳房子的更多相关文章
- 洛谷【P5004 专心OI - 跳房子】 题解
题目链接 https://www.luogu.org/problem/P5004 洛谷 P5004 专心OI - 跳房子 Imakf有一天参加了PINO 2017 PJ组,他突然看见最后一道题 他十分 ...
- [luogu5004]专心OI - 跳房子【矩阵加速+动态规划】
传送门:https://www.luogu.org/problemnew/show/P5004 分析 动态规划转移方程是这样的\(f[i]=\sum^{i-m-1}_{j=0}f[j]\). 那么很明 ...
- 「P5004」专心OI - 跳房子 解题报告
题面 把\(N\)个无色格子排成一行,选若干个格子染成黑色,要求每个黑色格子之间至少间隔\(M\)个格子,求方案数 思路: 矩阵加速 根据题面,这一题似乎可以用递推 设第\(i\)个格子的编号为\(i ...
- P5002 专心OI - 找祖先
P5002 专心OI - 找祖先 给定一棵有根树(\(n \leq 10000\)),\(M \leq 50000\) 次询问, 求以 \(x\) 为 \(LCA\) 的点对个数 错误日志: 看下面 ...
- 【洛谷 5002】专心OI - 找祖先 (树上计数)
专心OI - 找祖先 题目背景 \(Imakf\)是一个小蒟蒻,他最近刚学了\(LCA\),他在手机\(APP\)里看到一个游戏也叫做\(LCA\)就下载了下来. 题目描述 这个游戏会给出你一棵树,这 ...
- luogu P5002 专心OI - 找祖先
题目描述 这个游戏会给出你一棵树,这棵树有NN个节点,根结点是RR,系统会选中MM个点P_1,P_2...P_MP 1 ,P 2 ...P M ,要Imakf回答有多少组点对(u_i,v_ ...
- 洛谷P5002 专心OI - 找祖先
题目概括 题目描述 这个游戏会给出你一棵树,这棵树有\(N\)个节点,根结点是\(R\),系统会选中\(M\)个点\(P_1,P_2...P_M\). 要Imakf回答有多少组点对\((u_i,v_i ...
- [luogu5002]专心OI - 找祖先
[传送门] 我们还是先将一下算法的步骤,待会再解释起来方便一点. 算法步骤 首先我们算出每个子树的\(size\). 我们就设当前访问的节点 然后我们就得到了当前这个节点的答案是这个树整个的\(siz ...
- 关于我的OI生涯(AFO){NOIP2016 后}
这篇我就随意写啦~不用统一的“题解”形式.♪(^∀^●)ノ 也分好几次慢慢更吧~ 对于NOIP2016的总结,我本想善始善终back回,但是心情不足以支撑我,那就只能有始有终了......下面进入我的 ...
随机推荐
- 安装部署NetBeans mysql Tomact joget workflow 环境
一.安装joget workflow 1.安装jdk 下载jdk http://www.oracle.com/technetwork/java/javase/downloads/index.html ...
- 8.2.3 覆写 Equals
经过对四种不同类型判等方法的讨论,我们不难发现不管是 Equals 静态方法.Equals 虚方法 抑或==操作符的执行结果,都可能受到覆写 Equals 方法的影响.因此研究对象判等就必须将注意 力 ...
- php中fopen不能创建中文文件名文件的问题
之前网页的chartset用的是utf-8,文件也用utf-8,然后用fopen()创建一个中文文件名的文件时问题就出来了,文件名都是乱 码! 查看了很多文档试了不少方法都解决不了,本来想着用别的方法 ...
- Light Oj - 1134 Be Efficient
题目传送门:Be Efficient 题意:输入n和m,然后输入有n个元素的一个序列,问有多少个子序列元素的和能整除m. 思路:求前缀和,利用一个前缀的一个定理求解. 前缀和的一个定理是:每次求的前缀 ...
- Linux:安装CentOS 6.x和CentOS 7.x
1,准备镜像,这里到阿里云镜像网站下载 https://opsx.alibaba.com/mirror 2,安装CentOS6.10 打开vmware workstation--> 典型--&g ...
- HTML学习笔记之HTML5新特性
目录 1.拖放 2.画布 3.可伸缩矢量图形 4.地理定位 5.Web 存储 6.应用缓存 7.Web Worker 1.拖放 拖放是一种常见的特性,用于抓取对象以后拖到另一个位置,它是 HTML5 ...
- 搭建 Seafile 专属网盘
准备域名 任务时间:15min ~ 20min 域名注册 如果您还没有域名,可以在腾讯云上选购,过程可以参考下面的视频. 视频 - 在腾讯云上购买域名 域名解析 域名购买完成后, 需要将域名解析到实验 ...
- 解决Eclipse导入项目后Validating验证缓慢的问题
减少不必要的验证即可 步骤:Window-Preferences-左侧的Validation 如图所示,将Build一列的勾全部去掉就好了. 如需手动校验,右键项目名-选择Validate即可.
- mysql-索引、导入、导出、备份、恢复
1.索引 索引是一种与表有关的结构,它的作用相当于书的目录,可以根据目录中的页码快速找到所需的内容. 当表中有大量记录时,若要对表进行查询,没有索引的情况是全表搜索:将所有记录一一取出,和查询条件进行 ...
- [tsA1490][2013中国国家集训队第二次作业]osu![概率dp+线段树+矩阵乘法]
这样的题解只能舔题解了,,,qaq 清橙资料里有.. #include <iostream> #include <cstdio> #include <cstdlib> ...