bzoj 3120 矩阵优化DP
我的第一道需要程序建矩阵的矩阵优化DP。
题目可以将不同的p分开处理。
对于p==0 || p==1 直接是0或1
对于p>1,就要DP了。这里以p==3为例:
设dp[i][s1][s2][r]为前i列,结尾为0的有s1行(0表示女生,1表示男生),结尾为01的有s2个,结尾为011的有n-s1-s2个,有r列全是1的方案数。
状态这么复杂,看起来一点也不能用矩阵优化,但我们可以将状态(s1,s2,r)hash成整数,然后建立状态之间的转移。
收获:
这种m超过10^7的一般都要用矩阵优化,如果状态很复杂,可以将复杂的状态(但一般不多)hash成整数,然后用计算机建立状态之间的转移,然后就可以用矩阵优化了。
/**************************************************************
Problem: 3120
User: idy002
Language: C++
Result: Accepted
Time:24504 ms
Memory:2616 kb
****************************************************************/ #include <cstdio>
#include <cstring>
#define M 1000000007
#define maxs 200 typedef long long dint; int n, p, q;
dint m;
int comb[][]; void init_comb() {
for( int i=; i<=; i++ )
for( int j=; j<=i; j++ ) {
if( j== || i==j )
comb[i][j]=;
else
comb[i][j] = (comb[i-][j]+comb[i-][j-]);
}
}
struct Matrix {
int n;
dint v[maxs][maxs];
void init( int nn ) {
n=nn;
for( int i=; i<n; i++ )
for( int j=; j<n; j++ )
v[i][j]=;
}
void make_unit( int nn ) {
n=nn;
for( int i=; i<n; i++ )
for( int j=; j<n; j++ )
v[i][j] = i==j;
}
Matrix operator*( const Matrix & b ) const {
const Matrix & a = *this;
Matrix rt;
memset( &rt, , sizeof(rt) );
rt.n = b.n;
for( int k=; k<n; k++ ) {
for( int i=; i<n; i++ ) {
if( a.v[i][k] ) {
for( int j=; j<n; j++ ) {
if( b.v[k][j] ) {
rt.v[i][j] += (a.v[i][k]*b.v[k][j])%M;
if( rt.v[i][j]>=M ) rt.v[i][j]-=M;
}
}
}
}
}
/*
for( int i=0; i<n; i++ ) {
for( int j=0; j<n; j++ ) {
rt.v[i][j] = 0;
for( int k=0; k<n; k++ ) {
rt.v[i][j] += (a.v[i][k]*b.v[k][j])%M;
if( rt.v[i][j]>=M )
rt.v[i][j]-=M;
}
}
}
*/
return rt;
}
}; Matrix mpow( Matrix a, dint b ) {
Matrix rt;
for( rt.make_unit(a.n); b; b>>=,a=a*a )
if( b& ) rt=(rt*a);
return rt;
}
namespace Sec1 {
void sov(){
if( p== ) printf( "0\n" );
else if( p== ) printf( "1\n" );
}
}
namespace Sec2 {
int info[maxs][], idx[][], tot;
Matrix trans;
void init() {
for( int r=; r<=q; r++ )
for( int a=; a<=n; a++ ) {
info[tot][] = a;
info[tot][] = n-a;
info[tot][] = r;
idx[a][r] = tot;
tot++;
}
trans.init(tot);
for( int s=; s<tot; s++ ) {
int a=info[s][], r=info[s][];
for( int sa=; sa<=a; sa++ ) {
int na=n-sa, nr=r+(sa==n);
if( nr>q ) continue;
int ns=idx[na][nr];
trans.v[s][ns] = comb[a][sa];
}
}
}
void sov() {
init();
trans = mpow( trans, m );
int row = idx[n][];
dint ans=;
for( int i=; i<tot; i++ ) {
ans += trans.v[row][i];
if( ans>=M ) ans-=M;
}
printf( "%lld\n", ans );
}
}
namespace Sec3 {
int info[maxs][], idx[][][], tot;
Matrix trans;
void init() {
for( int r=; r<=q; r++ )
for( int a=; a<=n; a++ )
for( int b=; b<=n-a; b++ ) {
info[tot][] = a;
info[tot][] = b;
info[tot][] = n-a-b;
info[tot][] = r;
idx[a][b][r] = tot;
tot++;
}
trans.n = tot;
for( int s=; s<tot; s++ ) {
int a=info[s][], b=info[s][], c=info[s][], r=info[s][];
for( int sa=; sa<=a; sa++ )
for( int sb=; sb<=b; sb++ ) {
int na=c+a-sa+b-sb, nb=sa, nr=r+(sa+sb==n);
if( nr>q ) continue;
int ns = idx[na][nb][nr];
trans.v[s][ns] = comb[a][sa]*comb[b][sb];
}
}
}
void sov(){
init();
trans = mpow( trans, m );
int row = idx[n][][];
dint ans=;
for( int i=; i<tot; i++ ) {
ans += trans.v[row][i];
if( ans>=M ) ans-=M;
}
printf( "%lld\n", ans );
}
} int main() {
scanf( "%d%lld%d%d", &n, &m, &p, &q );
init_comb();
if( p<= ) Sec1::sov();
else if( p== ) Sec2::sov();
else if( p== ) Sec3::sov();
}
bzoj 3120 矩阵优化DP的更多相关文章
- 矩阵优化dp
链接:https://www.luogu.org/problemnew/show/P1939 题解: 矩阵优化dp模板题 搞清楚矩阵是怎么乘的构造一下矩阵就很简单了 代码: #include < ...
- HDU - 2294: Pendant(矩阵优化DP&前缀和)
On Saint Valentine's Day, Alex imagined to present a special pendant to his girl friend made by K ki ...
- [六省联考2017]组合数问题 (矩阵优化$dp$)
题目链接 Solution 矩阵优化 \(dp\). 题中给出的式子的意思就是: 求 nk 个物品中选出 mod k 为 r 的个数的物品的方案数. 考虑朴素 \(dp\) ,定义状态 \(f[i][ ...
- bzoj 1009 [HNOI2008]GT考试——kmp+矩阵优化dp
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1009 首先想到 确保模式串不出现 就是 确保每个位置的后缀不是该模式串. 为了dp,需要记录 ...
- [Sdoi2017]序列计数 矩阵优化dp
题目 https://www.lydsy.com/JudgeOnline/problem.php?id=4818 思路 先考虑没有质数限制 dp是在同余系下的,所以\(f[i][j]\)表示前i个点, ...
- 矩阵优化DP类问题应用向小结
前言 本篇强调应用,矩阵的基本知识有所省略(也许会写篇基础向...). 思想及原理 为什么Oier们能够想到用矩阵来加速DP呢?做了一些DP题之后,我们会发现,有时候DP两两状态之间的转移是定向的,也 ...
- 洛谷P3193 GT考试 kmp+矩阵优化dp
题意 求\(N\)位数字序列(可以有前导0)中不出现某\(M\)位子串的个数,模\(K\). \(N<=10^9,M<=20,K<=1000\) 分析 设\(dp[i][j]\)表示 ...
- $[TJOI2017]$ 可乐 矩阵优化$dp$
\(Sol\) 设\(f_i\)为到第\(i\)秒的方案数,显然\(f_i=\)在第\(i\)秒前爆炸的方案数+在第\(i\)秒爆炸的方案数+在第\(i\)秒停下的方案数+在第\(i\)秒走向下一个城 ...
- bzoj 1096 斜率优化DP
首先比较容易的看出来是DP,w[i]为前i个工厂的最小费用,那么w[i]=min(w[j-1]+cost(j,i))+c[i],但是这样是不work的,复杂度上明显过不去,这样我们考虑优化DP. 设A ...
随机推荐
- sublime 直接运行php代码
只需要简单的配置就可以进行 操作. 首先配置php环境变量 配置完成后打开sublime 点击新编译系统 { "cmd": ["php", "$fil ...
- [转载]Android中Bitmap和Drawable
一.相关概念 1.Drawable就是一个可画的对象,其可能是一张位图(BitmapDrawable),也可能是一个图形(ShapeDrawable),还有可能是一个图层(LayerDrawable) ...
- C/C++——二维数组与指针、指针数组、数组指针(行指针)、二级指针的用法
本文转载自:https://blog.csdn.net/qq_33573235/article/details/79530792 1. 二维数组和指针 要用指针处理二维数组,首先要解决从存储的角度对二 ...
- [ python ] 练习作业 - 1
1,写代码,有如下列表,按照要求实现每一个功能 li = ["alex","wusir","eric","rain",& ...
- java基础9 main函数、this、static、super、final、instanceof 关键字
一.main函数详解 1.public:公共的.权限是最大的,在任何情况都可以访问 原因:为了保证jvm在任何情况下都可以访问到main法2.static:静态,静态可以让jvm调用更方便,不需要用 ...
- json数据操作
<!DOCTYPE HTML> <html> <head> <meta charset="utf-8"> <title> ...
- python【项目】:选课系统【简易版】
功能要求 角色:学校.学员.课程.讲师要求:1. 创建学校2. 创建课程3. 课程包含,周期,价格,通过学校创建课程4. 通过学校创建班级, 班级关联课程.讲师5. 创建学员时,选择学校,关联班级5. ...
- 51Nod 1352 集合计数(扩展欧几里德)
题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1352 题目大意: 给出N个固定集合{1,N},{2,N-1} ...
- (转载)Linux入门:操作目录和文件的命令
PATH 每个用户的PATH都是不一样的: PATH中不包含“当前目录”: (1)echo $PATH:显示PATH环境变量: (2)PATH = "$PATH":/home/ ...
- AC日记——#2054. 「TJOI / HEOI2016」树
#2054. 「TJOI / HEOI2016」树 思路: 线段树: 代码: #include <cstdio> #include <cstring> #include < ...