题目大意

  有一个数轴。yww 最开始在位置 \(0\)。yww 总共要跳跃很多次。每次 yww 可以往右跳 \(1\) 单位长度,或者跳到位置 \(1\)。

  定义位置序列为 yww 在每次跳跃之后所在的位置组成的序列(显然不包括 \(0\))。

  有 \(k\) 个数是好的,分别为 \(a_1,a_2,\ldots,a_k\)。

  定义一个位置序列是好的当且仅当:

  • 所有好的数的出现次数之和为 \(n\) 。
  • 序列中最后一个数是好的。
  • 对于每一个长度为 \(m\) 的子区间,区间内至少有一个好的数。

  定义两个位置序列本质相同当且仅当:

  • 这两个位置序列的长度相同。
  • 不存在一个数 \(t\),满足其中一个序列的第 \(t\) 项是一个好的数,且另一个序列的第 \(t\) 项不是一个好的数。

  求所有本质不同的好的位置序列的长度之和。

  对 \({10}^9+7\) 取模。

  \(k\leq 100,n,m\leq {10}^9\)

题解

  记 \(b_i=a_i-a_{i-1}\)。

  考虑对于一个最终位置是好的点的位置序列,求出和这个序列本质相同的序列中,最终能到达那些点。

  这样就有一个 \(O(2^kn)\) 的DP了。

  如果你把这个做法写出来,就会发现其实只有 \(O(k)\) 个状态是有用的。

  这是为什么呢?

  对于一个位置集合 \(S\),考虑集合内最大的元素 \(x\),对于一个更小的 \(y\),\(y\in S\) 当且仅当 \(b_1\leq b_{x-y+1}\) 且 \(b_{2\ldots y}=b_{x-y+2 \ldots x}\) 这样对于每个 \(x\),\(S\) 是唯一的。

  直接套个矩阵快速幂优化DP就 \(O(k^3\log n)\) 了。


  还可以换一种方向思考。

  考虑对于一个好的序列,每次取一个最短的前缀,满足后面还是合法的好的序列。

  如果一个前缀能被分成几个前缀拼在一起,就不能取这个前缀了。

  处理出删掉 \(b_1\) 之后的 ex_kmp 数组就可以快速求出每个前缀是否可选。

  这就是一个常系数齐次线性递推。

  直接BM+倍增取模可以做到 \(O(k^2+k\log k\log n)\)

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<ctime>
#include<functional>
#include<cmath>
#include<vector>
#include<assert.h>
#include<map>
//using namespace std;
using std::min;
using std::max;
using std::swap;
using std::sort;
using std::reverse;
using std::random_shuffle;
using std::lower_bound;
using std::upper_bound;
using std::unique;
using std::vector;
using std::map;
typedef long long ll;
typedef unsigned long long ull;
typedef double db;
typedef std::pair<int,int> pii;
typedef std::pair<ll,ll> pll;
void open(const char *s){
#ifndef ONLINE_JUDGE
char str[100];sprintf(str,"%s.in",s);freopen(str,"r",stdin);sprintf(str,"%s.out",s);freopen(str,"w",stdout);
#endif
}
void open2(const char *s){
#ifdef DEBUG
char str[100];sprintf(str,"%s.in",s);freopen(str,"r",stdin);sprintf(str,"%s.out",s);freopen(str,"w",stdout);
#endif
}
int rd(){int s=0,c,b=0;while(((c=getchar())<'0'||c>'9')&&c!='-');if(c=='-'){c=getchar();b=1;}do{s=s*10+c-'0';}while((c=getchar())>='0'&&c<='9');return b?-s:s;}
void put(int x){if(!x){putchar('0');return;}static int c[20];int t=0;while(x){c[++t]=x%10;x/=10;}while(t)putchar(c[t--]+'0');}
int upmin(int &a,int b){if(b<a){a=b;return 1;}return 0;}
int upmax(int &a,int b){if(b>a){a=b;return 1;}return 0;}
const int K=110;
const ll p=1000000007;
int k,m,n;
template <typename T>
T operator +(T a,T b)
{
return T(a.first+b.first,a.second+b.second);
}
template <typename T>
T operator *(T a,T b)
{
return T(a.first*b.first,a.first*b.second+a.second*b.first);
}
struct mat
{
pii a[K][K];
mat()
{
memset(a,0,sizeof a);
}
pii *operator [](int x)
{
return a[x];
}
};
mat operator *(mat a,mat b)
{
mat c;
for(int i=1;i<=k;i++)
for(int j=1;j<=k;j++)
{
std::pair<__int128,__int128> s;
for(int l=1;l<=k;l++)
{
s.first+=(ll)a[i][l].first*b[l][j].first;
s.second+=(ll)a[i][l].first*b[l][j].second;
s.second+=(ll)a[i][l].second*b[l][j].first;
}
c[i][j]=pii(s.first%p,s.second%p);
}
return c;
}
mat fp(mat a,ll b)
{
mat s;
for(int i=1;i<=k;i++)
s[i][i]=pll(1,0);
for(;b;b>>=1,a=a*a)
if(b&1)
s=s*a;
return s;
}
int b[K][K];
int a[K];
mat c,d;
map<int,int> s;
int sum(ll l,ll r)
{
return (l+r)*(r-l+1)/2%p;
}
int main()
{
open("jump");
scanf("%d%d%d",&k,&m,&n);
k=min(k,n);
for(int i=1;i<=k;i++)
scanf("%d",&a[i]);
for(int i=k;i>=2;i--)
a[i]-=a[i-1];
if(a[1]>m)
{
printf("0\n");
return 0;
}
for(int i=2;i<=k;i++)
if(a[i]>m)
k=i;
for(int i=1;i<=k;i++)
{
b[i][i]=1;
for(int j=1;j<i;j++)
{
int flag=1;
if(a[1]>a[i-j+1])
flag=0;
for(int l=2;flag&&l<=j;l++)
if(a[l]!=a[i-j+l])
flag=0;
b[i][j]=flag;
}
}
for(int i=1;i<=k;i++)
{
int cnt=m-a[1]+1;
ll _s=sum(a[1],m);
s.clear();
for(int j=min(i,k-1);j>=1;j--)
if(b[i][j]&&!s[a[j+1]])
{
s[a[j+1]]=1;
c[i][j+1]=pll(1,a[j+1]);
if(a[j+1]>=a[1])
{
cnt--;
_s=(_s-a[j+1])%p;
}
}
c[i][1]=pll(cnt,_s);
}
d[1][1]=pll(m-a[1]+1,sum(a[1],m));
c=fp(c,n-1);
d=d*c;
// for(int i=1;i<n;i++)
// d=d*c;
ll ans=0;
for(int i=1;i<=k;i++)
ans=(ans+d[1][i].second)%p;
ans=(ans%p+p)%p;
printf("%lld\n",ans);
return 0;
}

【CSA49G】【XSY3315】jump DP的更多相关文章

  1. 【BZOJ-1260】涂色paint 区间DP

    1260: [CQOI2007]涂色paint Time Limit: 30 Sec  Memory Limit: 64 MBSubmit: 1147  Solved: 698[Submit][Sta ...

  2. 【POJ 2096】Collecting Bugs 概率期望dp

    题意 有s个系统,n种bug,小明每天找出一个bug,可能是任意一个系统的,可能是任意一种bug,即是某一系统的bug概率是1/s,是某一种bug概率是1/n. 求他找到s个系统的bug,n种bug, ...

  3. 【NOIP 2014 DAY1 T3】飞扬的小鸟(DP)

    题目描述 Flappy Bird 是一款风靡一时的休闲手机游戏.玩家需要不断控制点击手机屏幕的频率来调节小鸟的飞行高度,让小鸟顺利通过画面右方的管道缝隙.如果小鸟一不小心撞到了水管或者掉在地上的话,便 ...

  4. 【BZOJ2281】【博弈论+DP】 [Sdoi2011]黑白棋

    Description 黑白棋(game) [问题描述] 小A和小B又想到了一个新的游戏. 这个游戏是在一个1*n的棋盘上进行的,棋盘上有k个棋子,一半是黑色,一半是白色. 最左边是白色棋子,最右边是 ...

  5. 【一天一道LeetCode】#55. Jump Game

    一天一道LeetCode系列 (一)题目 Given an array of non-negative integers, you are initially positioned at the fi ...

  6. 【GDOI2016模拟3.15】基因合成(回文串+性质+DP)

    [GDOI2016模拟3.15]基因合成 题意: 给一个目标串,要求从空串进行最少的操作次数变成目标串,操作有两种: 在串的头或尾加入一个字符. 把串复制一遍后反向接到串的末尾. 因为有回文操作,所以 ...

  7. 【noip模拟赛5】细菌 状压dp

    [noip模拟赛5]细菌   描述 近期,农场出现了D(1<=D<=15)种细菌.John要从他的 N(1<=N<=1,000)头奶牛中尽可能多地选些产奶.但是如果选中的奶牛携 ...

  8. 【UOJ#422】【集训队作业2018】小Z的礼物(min-max容斥,轮廓线dp)

    [UOJ#422][集训队作业2018]小Z的礼物(min-max容斥,轮廓线dp) 题面 UOJ 题解 毒瘤xzy,怎么能搬这种题当做WC模拟题QwQ 一开始开错题了,根本就不会做. 后来发现是每次 ...

  9. 【noip模拟赛5】任务分配 降维dp

    描述 现有n个任务,要交给A和B完成.每个任务给A或给B完成,所需的时间分别为ai和bi.问他们完成所有的任务至少要多少时间. 输入 第一行一个正整数n,表示有n个任务.接下来有n行,每行两个正整数a ...

  10. 【洛谷】3953:逛公园【反向最短路】【记忆化搜索(DP)统计方案】

    P3953 逛公园 题目描述 策策同学特别喜欢逛公园.公园可以看成一张N个点M条边构成的有向图,且没有 自环和重边.其中1号点是公园的入口,N号点是公园的出口,每条边有一个非负权值, 代表策策经过这条 ...

随机推荐

  1. c#进阶一:使用ILDASM来查看c#中间语言

    平时工作的时候总是使用ctrl c+ctrl v去快速开发实现业务功能,但是在工作之余,我们也应该要注意静下心来去学习和提高自己.进阶的文章随性来写,不定时更新.希望可以和大家共同学习,共同进步.今天 ...

  2. 我爱Java系列之《JavaEE面试宝典》---【IO流面试总结】

    1.什么是比特(Bit),什么是字节(Byte),什么是字符(Char),它们长度是多少,各有什么区别 答案 Bit最小的二进制单位 ,是计算机的操作部分 取值0或者1 Byte是计算机操作数据的最小 ...

  3. 05 入门 - 浅谈 ASP.NET MVC程序的工作原理

    目录索引:<ASP.NET MVC 5 高级编程>学习笔记 本篇内容 1. Global.asax文件 2. RouteConfig.cs文件 3. 视图命名和寻址的规则 前面创建了一个简 ...

  4. 电脑获取手机文件的一种方式(通过手机建立ftp)

    1 打开手机热点. 2 手机需要安装es文件浏览器,在es浏览器首页有个远程管理(或在左侧网络功能下有个远程管理),打开即可启用手机目录下的ftp. 3 打开电脑按提示输入ftp站点.默认地址是手机热 ...

  5. HTML5 新增的 input 事件

    以往 HTML 的 input 輸入框,無法即時反映使用者的輸入內容.onkeyup.onkeydown 事件,無法即時.精確地取得使用者的輸入資料:而 onchange.onblur 事件,要等到失 ...

  6. Python 强制停止多线程运行

    强制停止多线程运行 by:授客 QQ:1033553122 #!/usr/bin/env python # -*- coding:utf-8 -*-     __author__ = 'shouke' ...

  7. 如何在Android studio上运行从github上下载的RN项目

    想要编译别人的RN项目,还是要踩踩坑才能走上正轨啊,分享下我试过多种方法后最喜欢的方法(其实是因为我多次用VS Code编译都是以失败而告终,所以才选择的studio) 注意:这一步是你的开发环境都安 ...

  8. Testlink1.9.17使用方法(第二章 登录&汉化设置)

    第二章 登录&汉化设置 QQ交流群:585499566 1,使用超级账户admin/admin登录. 2,登录后,会提示创建一个新的项目,先不要创建,先进入用户管理,设置成中文显示,也就是汉化 ...

  9. 如何自己制作CHM电子书?

    软件介绍: EasyCHM 非常适合个人和单位制作高压缩比的有目录.索引,同时具有全文检索及高亮显示搜索结果的网页集锦.CHM格式的帮助文件.专业的产品说明书.公司介绍.文章集锦.CHM电子书等等. ...

  10. mysql的进阶

    老师的博客:http://www.cnblogs.com/wupeiqi/articles/5713323.html 总结 导出与导入 导出:mysqldump -u root -p 数据库 > ...