省选模拟赛 Problem 3. count (矩阵快速幂优化DP)
Discription
DarrellDarrellDarrell 在思考一道计算题。
给你一个尺寸为 1×N1 × N1×N 的长条,你可以在上面切很多刀,要求竖直地切并且且完后每块的长度都是整数。
在这种限制下其实只有 N−1N − 1N−1 个位置可以切。
对于一种切的方案,假如切完后每块的宽度分别是:w1,w2,w3,...,wk(∑wi=N)w_1, w_2, w_3, ..., w_k(\sum w_i = N)w1,w2,w3,...,wk(∑wi=N),那么该种方案对应
的完美值为:∏i=1kwi2
∏^{k}_{i=1}w_i^2i=1∏kwi2
那么问题来了,给出 MMM 个位置不能切(如果用 xxx 表示一个位置,那么切完该位置后长条变为 1×x1 × x1×x 和
1×(N−x)1 × (N − x)1×(N−x) 两块),那么所有合法切法对应的完美值的和是多少呢?(只需要输出模 109+710^9 + 7109+7 的结果)
Input
第 111 行,有 222 个整数:NMN MNM,表示长条的总长度及不能切的位置数
第 222 行,有 MMM 个整数:x1,x2,x3,...,xMx_1, x_2, x_3, ..., x_Mx1,x2,x3,...,xM 表示不能切的位置。
Output
输出 111 行,包含 111 个整数,表示满足要求的所有切法对应的完美值和。(对 109+710^9 + 7109+7 取模后的结果)
Note
• 对于 20%20\%20% 的数据,有 1≤N,M≤1031 ≤ N, M ≤ 10^31≤N,M≤103。
• 对于 60%60\%60% 的数据,有 1≤N,M≤1051 ≤ N, M ≤ 10^51≤N,M≤105。
• 对于 100%100\%100% 的数据,有 1≤N≤109,1≤M≤1051 ≤ N ≤ 10^9,1 ≤ M ≤ 10^51≤N≤109,1≤M≤105,且 1≤x1<x2<x3<...<xm<N1 ≤ x_1 < x_2 < x_3 < ... < x_m < N1≤x1<x2<x3<...<xm<N
很显然可以看出DPDPDP柿子dp[0]=1, dp[i]=∑j=0i−1dp[j]∗(i−j)2dp[0]=1,\ \ \ dp[i]=\sum_{j=0}^{i-1}dp[j]*(i-j)^2dp[0]=1, dp[i]=j=0∑i−1dp[j]∗(i−j)2
然后答案就为dp[N]dp[N]dp[N]
由于NNN很大 ≤109\le10^9≤109
所以考虑用矩阵快速幂优化转移
先想想M=0M=0M=0怎么转移
定义向量如下:[ ∑j=0idp[j] , ∑j=0idp[j]∗(i−j) , ∑j=0idp[j]∗(i−j)2 ]\left[\ \ \ \sum_{j=0}^idp[j]\ ,\ \sum_{j=0}^idp[j]*(i-j)\ ,\ \sum_{j=0}^idp[j]*(i-j)^2\ \ \ \right][ j=0∑idp[j] , j=0∑idp[j]∗(i−j) , j=0∑idp[j]∗(i−j)2 ]
然后考虑从[ ∑j=0i−1dp[j] , ∑j=0i−1dp[j]∗(i−1−j) , ∑j=0i−1dp[j]∗(i−1−j)2 ]\left[\ \ \ \sum_{j=0}^{i-1}dp[j]\ ,\ \sum_{j=0}^{i-1}dp[j]*(i-1-j)\ ,\ \sum_{j=0}^{i-1}dp[j]*(i-1-j)^2\ \ \ \right][ j=0∑i−1dp[j] , j=0∑i−1dp[j]∗(i−1−j) , j=0∑i−1dp[j]∗(i−1−j)2 ]转移到[ ∑j=0idp[j] , ∑j=0idp[j]∗(i−j) , ∑j=0idp[j]∗(i−j)2 ]\left[\ \ \ \sum_{j=0}^idp[j]\ ,\ \sum_{j=0}^idp[j]*(i-j)\ ,\ \sum_{j=0}^idp[j]*(i-j)^2\ \ \ \right][ j=0∑idp[j] , j=0∑idp[j]∗(i−j) , j=0∑idp[j]∗(i−j)2 ]
转移矩阵就是
[221110121][∑j=0i−1dp[j]∑j=0i−1dp[j]∗(i−1−j)∑j=0i−1dp[j]∗(i−1−j)2]=[∑j=0idp[j]∑j=0idp[j]∗(i−j)∑j=0idp[j]∗(i−j)2]\left[\begin{matrix}
2&2&1\\
1&1&0\\
1&2&1\\
\end{matrix}\right]
\left[\begin{matrix}
\sum_{j=0}^{i-1}dp[j]\\
\sum_{j=0}^{i-1}dp[j]*(i-1-j)\\
\sum_{j=0}^{i-1}dp[j]*(i-1-j)^2\\
\end{matrix}\right]
=\left[\begin{matrix}
\sum_{j=0}^{i}dp[j]\\
\sum_{j=0}^{i}dp[j]*(i-j)\\
\sum_{j=0}^{i}dp[j]*(i-j)^2\\
\end{matrix}\right]
⎣⎡211212101⎦⎤⎣⎢⎡∑j=0i−1dp[j]∑j=0i−1dp[j]∗(i−1−j)∑j=0i−1dp[j]∗(i−1−j)2⎦⎥⎤=⎣⎢⎡∑j=0idp[j]∑j=0idp[j]∗(i−j)∑j=0idp[j]∗(i−j)2⎦⎥⎤自己推一推吧…
注意第二项和第三项当j=ij=ij=i时贡献的值是000因为i−j=0i-j=0i−j=0,所以jjj的范围实质上是[0,i−1][0,i-1][0,i−1].为了统一就写成[0,i][0,i][0,i]了.
考虑这个地方不能切,我们就强制把这个位置的dpdpdp值设为000就行了.
那么不能切的地方的转移,就只用把第一项累加dp[i]dp[i]dp[i]的系数去掉就行了.第一行也就变成了[2,2,1]−[1,2,1]=[1,0,0][2,2,1]-[1,2,1]=[1,0,0][2,2,1]−[1,2,1]=[1,0,0],那么不能切的地方的转移矩阵就如下:
[100110121]\left[\begin{matrix}
1&0&0\\
1&1&0\\
1&2&1\\
\end{matrix}\right]⎣⎡111012001⎦⎤
详细见代码
CODE
#include<bits/stdc++.h>
using namespace std;
inline void read(int &num) {
char ch; int flg = 1; while(!isdigit(ch=getchar()))if(ch=='-')flg = -flg;
for(num=0; isdigit(ch); num=num*10+ch-'0', ch=getchar()); num*=flg;
}
const int MAXN = 1e5+5;
const int mod = 1e9+7;
struct mat {
int a[3][3];
mat() { memset(a,0,sizeof a); }
inline void init1() {
a[0][0] = 2; a[0][1] = 2; a[0][2] = 1;
a[1][0] = 1; a[1][1] = 1; a[1][2] = 0;
a[2][0] = 1; a[2][1] = 2; a[2][2] = 1;
}
inline void init2() {
a[0][0] = 1; a[0][1] = 0; a[0][2] = 0;
a[1][0] = 1; a[1][1] = 1; a[1][2] = 0;
a[2][0] = 1; a[2][1] = 2; a[2][2] = 1;
}
inline mat operator *(const mat &o)const {
mat re;
for(int k = 0; k < 3; ++k)
for(int i = 0; i < 3; ++i) if(a[i][k])
for(int j = 0; j < 3; ++j) if(o.a[k][j])
re.a[i][j] = (re.a[i][j] + 1ll * a[i][k] * o.a[k][j] % mod) % mod;
return re;
}
inline mat operator ^(int b)const {
mat A = *this, re;
re.a[0][0] = re.a[1][1] = re.a[2][2] = 1;
while(b) {
if(b & 1) re = re * A;
A = A * A; b >>= 1;
}
return re;
}
}ans, trans1, trans2;
int N, M, pos[MAXN];
int main() {
freopen("count.in", "r", stdin);
freopen("count.out", "w", stdout);
scanf("%d%d", &N, &M);
for(int i = 1; i <= M; ++i)
scanf("%d", &pos[i]);
ans.a[0][0] = 1;
trans1.init1();
trans2.init2();
for(int i = 1; i <= M; ++i)
ans = (trans1^(pos[i]-pos[i-1]-1)) * ans, ans = trans2 * ans;
ans = (trans1^(N-pos[M])) * ans;
printf("%d\n", ans.a[2][0]);
}
妈妈我终于会矩阵快速幂了!!!
省选模拟赛 Problem 3. count (矩阵快速幂优化DP)的更多相关文章
- 2018.10.23 bzoj1297: [SCOI2009]迷路(矩阵快速幂优化dp)
传送门 矩阵快速幂优化dp简单题. 考虑状态转移方程: f[time][u]=∑f[time−1][v]f[time][u]=\sum f[time-1][v]f[time][u]=∑f[time−1 ...
- 2018.10.22 bzoj1009: [HNOI2008]GT考试(kmp+矩阵快速幂优化dp)
传送门 f[i][j]f[i][j]f[i][j]表示从状态"匹配了前i位"转移到"匹配了前j位"的方案数. 这个东西单次是可以通过跳kmp的fail数组得到的 ...
- 2018.10.16 uoj#340. 【清华集训2017】小 Y 和恐怖的奴隶主(矩阵快速幂优化dp)
传送门 一道不错的矩阵快速幂优化dpdpdp. 设f[i][j][k][l]f[i][j][k][l]f[i][j][k][l]表示前iii轮第iii轮还有jjj个一滴血的,kkk个两滴血的,lll个 ...
- 【bzoj1009】[HNOI2008]GT考试(矩阵快速幂优化dp+kmp)
题目传送门:https://www.lydsy.com/JudgeOnline/problem.php?id=1009 这道题一看数据范围:$ n<=10^9 $,显然不是数学题就是矩乘快速幂优 ...
- 2018.10.19 NOIP模拟 硬币(矩阵快速幂优化dp)
传送门 不得不说神仙出题人DZYODZYODZYO出的题是真的妙. f[i][j][k]f[i][j][k]f[i][j][k]表示选的硬币最大面值为iii最小面值不小于jjj,总面值为kkk时的选法 ...
- 2018.11.08 NOIP模拟 景点(倍增+矩阵快速幂优化dp)
传送门 首先按照题意构造出转移矩阵. 然后可以矩阵快速幂求出答案. 但是直接做是O(n3qlogm)O(n^3qlogm)O(n3qlogm)的会TTT掉. 观察要求的东西发现我们只关系一行的答案. ...
- 2019.02.11 bzoj4818: [Sdoi2017]序列计数(矩阵快速幂优化dp)
传送门 题意简述:问有多少长度为n的序列,序列中的数都是不超过m的正整数,而且这n个数的和是p的倍数,且其中至少有一个数是质数,答案对201704082017040820170408取模(n≤1e9, ...
- 【20181019T2】硬币【矩阵快速幂优化DP】
题面 [错解] 哎\(N \leq 50\)?双向搜索? 切了切-- 等下,好像要求方案数-- 好像搜不了 哎他给\(V_{i} | V_{i+1}\)干嘛? 肯定有用啊 为了体现条件的用处,我在搜下 ...
- HDU5411——CRB and Puzzle——————【矩阵快速幂优化dp】
CRB and Puzzle Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)To ...
随机推荐
- SQLServer 查询view中是否包含某个关键字
在数据库view的创建中,会遇到一些跨数据库的view脚本,但是在将view更新到production的时候可能忘记更改database name,导致出现一些问题. 以下脚本可以检查出包含某个关键字 ...
- python面向对象基础-01
面向对象(OOP)基本概念 前言 话说三国时期曹军于官渡大败袁绍,酒席之间,曹操诗兴大发,吟道:喝酒唱歌,人生真爽! 众将直呼:"丞相好诗",于是命印刷工匠刻板印刷以流传天下; 待 ...
- element-ui 时间设置 获取固定的时间格式
<el-date-picker v-model="time1" type="daterange" start-placeholder="开始日期 ...
- SAS学习笔记21 散点图、条形图
- POSIX异步I/O接口使用
POSIX1003.1b 实时扩展协议规定的标准异步 I/O 接口,即 aio_read 函数. aio_write 函数.aio_fsync 函数.aio_cancel 函数.aio_error 函 ...
- java之理解面向对象
1.程序设计的三种基本结构 顺序结构 顺序结构表示程序中的各操作是按照它们在源代码中的排列顺序依次执行的 选择结构 选择结构表示程序的处理需要根据某个特定的条件选择其中的一个分支执行.选择结构有单选择 ...
- 一次腾讯云centos服务器被入侵的处理
昨天一大早,我还没到公司呢,就收到腾讯云安全中心发来的服务器异常登录告警,登录控制台一看,ip还是美国的,一脸懵逼.由于本人之前也没有过处理服务器入侵的经验,而且这台服务器目前还没有部署商用系统,所以 ...
- 使用Java Executor框架实现多线程
本文将涵盖两个主题: 通过实现Callable接口创建线程 在Java中使用Executor框架 实现Callable接口 为了创建一段可以在线程中运行的代码,我们创建了一个类,然后实现了Callab ...
- JavaScript--Function对象(函数)的声明和作用域
Funtion 封装了可重复使用的代码块对象,函数名是一个引用函数对象的变量 声明提前:在程序开始执行之前,将var 变量和function函数提前声明 但赋值并不会提前 它的三种创建方法: 创建1 ...
- S2-048
前言 S2-048漏洞和struts2-struts1-plugin插件有关,该插件用于将Struts1的action也能在struts2上运行,提高兼容性(作用是我猜的~) 正文 我们先看下这个插件 ...