2019.2.26考试T2 矩阵快速幂加速DP

\(\color{#0066ff}{题解 }\)
可以发现, 数据范围中的n特别小,容易想到状压
可以想到类似于状压DP的思路,按列进行转移
那么应该有3维,\(f[i][j][k]\)代表到第i列,j的每一位表示这一行有多少连续的男生,k表示当前有多少列全是男生,的方案数
看到m的范围,我们肯定是要找一个\(O(logm)\)的东西加速转移,自然是矩阵加速
然后我们来看看有多少个状态,看看是否可行
j有\(p^n\)个,k有q个(用矩阵转移第一维自然不需要)
那么状态数依然达到了一个\(p^n*q=3^8*3=19683\)
这东西要是\(O(n^3)\)去转移绝对T到飞起,而且空间也是开不下
所以我们考虑减少状态的数量
发现,我们并不需要知道每一行当前有多少个连续的男生,我们只需要知道有多少行的连续的男生是\(0,1\dots p-1\)个
这相当于把一个数n拆分成p个数的和
这样的状态数绝对是少得多了,就可以矩阵加速了
我们可以通过dfs预处理出所有的状态(状态数极限$\le$200)
然后为了推出转移矩阵,我们需要考虑一个状态对另一个状态的贡献,直接\(n^2\)枚举即可
假设我们现在考虑\(x\to y\)的贡献
设\(x_0, x_1, x_2,xx\)表示状态x中,有连续0个男生的行的数量,有连续1个男生的行的数量,有连续2个男生的行的数量,有多少列全是男生,这个已经dfs预处理过,y同理
如果\(xx + 1 == yy\)
那就说明当前这一列必须全是男生,于是\(x_0\)要全给\(y_1\),\(x_1\)要全给\(y_2\),而且\(x_2\)必须为0,这样才有1的贡献
然后考虑不全为1的
我们肯定是放女生或男生,那么拿\(x_1\)来说,如果一些行放女生,那么这些行就要转移到\(y_0\),如果放男生,就要转移到\(y_2\),那么显然组合一下,方案就是\(C_{x_1}^{x_1-y_2}\),\(x_0\)同理
然后构造完转移矩阵,加速递推即可
#include<bits/stdc++.h>
#define LL long long
LL in() {
char ch; LL x = 0, f = 1;
while(!isdigit(ch = getchar()))(ch == '-') && (f = -f);
for(x = ch ^ 48; isdigit(ch = getchar()); x = (x << 1) + (x << 3) + (ch ^ 48));
return x * f;
}
const int mod = 1e9 + 7;
LL n, m, p, q, len;
struct Matrix {
LL ju[222][222];
Matrix() { memset(ju, 0, sizeof ju); }
void e() {
memset(ju, 0, sizeof ju);
for(int i = 1; i <= len; i++) ju[i][i] = 1;
}
friend Matrix operator * (const Matrix &a, const Matrix &b) {
Matrix c;
for(int i = 1; i <= len; i++)
for(int j = 1; j <= len; j++)
for(int k = 1; k <= len; k++)
(c.ju[i][j] += a.ju[i][k] * b.ju[k][j] % mod) %= mod;
return c;
}
Matrix ksm(LL y) {
Matrix x = *this, re;
re.e();
while(y) {
if(y & 1) re = re * x;
x = x * x;
y >>= 1;
}
return re;
}
}beg, A;
LL fac[22], inv[22];
int ls[22];
struct node {
int st[3], num;
node(int a = 0, int b = 0, int c = 0, int d = 0): num(d) {
st[0] = a, st[1] = b, st[2] = c;
}
}st[105050];
LL ksm(LL x, LL y) {
LL re = 1LL;
while(y) {
if(y & 1) re = re * x % mod;
x = x * x % mod;
y >>= 1;
}
return re;
}
LL C(int x, int y) {
return fac[x] * inv[y] % mod * inv[x - y] % mod;
}
void dfs(int dep, int tot) {
if(dep == p + 1) {
if(tot) return;
for(int i = 0; i <= q; i++) st[++len] = node(ls[1], ls[2], ls[3], i);
return;
}
for(int i = tot; i >= 0; i--) ls[dep] = i, dfs(dep + 1, tot - i);
}
void predoit() {
fac[0] = inv[0] = 1;
for(int i = 1; i <= 20; i++) fac[i] = 1LL * i * fac[i - 1] % mod, inv[i] = ksm(fac[i], mod - 2);
}
void work(const node &a, const node &b, int x, int y) {
int a1 = a.st[0], b1 = a.st[1], c1 = a.st[2], d1 = a.num;
int a2 = b.st[0], b2 = b.st[1], c2 = b.st[2], d2 = b.num;
if(d1 + 1 == d2) {
if(a1 == b2 && b1 == c2 && !c1) return (void)(A.ju[y][x]++);
} else if(d1 == d2) {
if(a1 == b2 && b1 == c2 && !c1) return;
if(a1 >= b2 && b1 >= c2) return (void)(A.ju[y][x] = C(a1, a1 - b2) * C(b1, b1 - c2) % mod);
}
}
void Build_Matrix() {
dfs(1, n);
#ifdef olinr
for(int i = 1; i <= len; i++) printf("%d %d %d %d\n", st[i].st[0], st[i].st[1], st[i].st[2], st[i].num);
#endif
for(int i = 1; i <= len; i++)
for(int j = 1; j <= len; j++)
work(st[i], st[j], i, j);
beg.ju[1][1] = 1;
}
void query() {
beg = A.ksm(m) * beg;
LL ans = 0;
for(int i = 1; i <= len; i++) (ans += beg.ju[i][1]) %= mod;
printf("%lld", ans);
}
int main() {
freopen("b.in", "r", stdin);
freopen("b.out", "w", stdout);
n = in(), m = in(), p = in(), q = in();
predoit();
Build_Matrix();
query();
return 0;
}
2019.2.26考试T2 矩阵快速幂加速DP的更多相关文章
- [bzoj1009](HNOI2008)GT考试 (kmp+矩阵快速幂加速递推)
Description 阿 申准备报名参加GT考试,准考证号为N位数X1X2....Xn(0<=Xi<=9),他不希望准考证号上出现不吉利的数字.他的不吉利数学 A1A2...Am(0&l ...
- bzoj1009 [HNOI2008]GT考试——KMP+矩阵快速幂优化DP
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1009 字符串计数DP问题啊...连题解都看了好多好久才明白,别提自己想出来的蒟蒻我... 首 ...
- 【bzoj1009】[HNOI2008]GT考试(矩阵快速幂优化dp+kmp)
题目传送门:https://www.lydsy.com/JudgeOnline/problem.php?id=1009 这道题一看数据范围:$ n<=10^9 $,显然不是数学题就是矩乘快速幂优 ...
- HDU 5950 - Recursive sequence - [矩阵快速幂加速递推][2016ACM/ICPC亚洲区沈阳站 Problem C]
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5950 Farmer John likes to play mathematics games with ...
- CH 3401 - 石头游戏 - [矩阵快速幂加速递推]
题目链接:传送门 描述石头游戏在一个 $n$ 行 $m$ 列 ($1 \le n,m \le 8$) 的网格上进行,每个格子对应一种操作序列,操作序列至多有 $10$ 种,分别用 $0 \sim 9$ ...
- 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 ...
- HDU5411——CRB and Puzzle——————【矩阵快速幂优化dp】
CRB and Puzzle Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)To ...
- Codeforces Round #420 (Div. 2) E. Okabe and El Psy Kongroo DP+矩阵快速幂加速
E. Okabe and El Psy Kongroo Okabe likes to take walks but knows that spies from the Organization ...
- HDU 1757 矩阵快速幂加速递推
题意: 已知: 当x<10时:f(x)=x 否则:f(x) = a0 * f(x-1) + a1 * f(x-2) + a2 * f(x-3) + --+ a9 * f(x-10); 求:f(x ...
随机推荐
- DCloud-MUI:HBuilder 安装
ylbtech-DCloud-MUI:HBuilder 安装 1.返回顶部 1. 2. 3. 4. 2.返回顶部 3.返回顶部 4.返回顶部 5.返回顶部 6.返回顶部 7.返 ...
- mycat接oracle和mysql多个实例
Mycat 后面接一个Oracle实例与一个MySQL实例,假设用户表,订单表,转账记录表,Oracle字符集为GBK的,MySQL字符集则要求UTF8的完成用户表与订单表到MySQL的迁移过程,要求 ...
- Python数据库(一)-Mysql数据库的连接
首先需要安装pymysql模块 然后用pymysql连接mysql并执行命令来查看数据 连接mysql数据库后需要创建游标来执行SQL语句 # -*- coding:utf-8 -*- __autho ...
- 无人零售的黑科技:RFID技术
无人零售的黑科技:RFID技术说起最近的热门话题,“无人零售商店”当属其一.自去年底,亚马逊推出第一家无人实体超市Amazon Go,到阿里.京东.大润发等各大企业纷纷加入,无人商店被推上了风口浪尖. ...
- 部署和调优 1.8 samba 部署和优化-2
Samba 可以实现 Linux 和 Windows 机器相互共享文件,这对我们来说是非常实用的.下面做几个实践,来了解samba,注意:在实践之前,请先检测 Selinux 是否关闭,否则可能会实践 ...
- eclipse安卓模拟器Failed to install on device 'emulator-5554': timeout处理方案
我们在用模拟器调试的时候,经常会出现Failed to install on device 'emulator-5554': timeout这个错误.其实就是有些虚拟器在部署的时候时间过于长.系统就认 ...
- VI中的多行删除与复制(转)
VI中的多行删除与复制 法一: 单行删除,:(待删除行)d 多行删除 ,:,10d 法二: 光标所在行,dd 光标所在行以下的N行,Ndd 方法1: 光标放到第6行, 输入:2yy 光标放到第9行, ...
- apache2不识别php
sudo apt-get install libapache2-mod-php7.0 sudo a2enmod php7.0 sudo service apache2 restart 注意:Apach ...
- saltstact的安装与配置
Saltstack是一个服务器基础架构集中化管理平台,具备配置管理.远程执行.监控等功能,人们一般习惯把saltstack比作成简化版的puppet和加强版的func.saltstack基于Pytho ...
- sharepoint文档库中日期显示详细日期,不显示几天前
文档库---库设置----栏