我的第一道需要程序建矩阵的矩阵优化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的更多相关文章

  1. 矩阵优化dp

    链接:https://www.luogu.org/problemnew/show/P1939 题解: 矩阵优化dp模板题 搞清楚矩阵是怎么乘的构造一下矩阵就很简单了 代码: #include < ...

  2. HDU - 2294: Pendant(矩阵优化DP&前缀和)

    On Saint Valentine's Day, Alex imagined to present a special pendant to his girl friend made by K ki ...

  3. [六省联考2017]组合数问题 (矩阵优化$dp$)

    题目链接 Solution 矩阵优化 \(dp\). 题中给出的式子的意思就是: 求 nk 个物品中选出 mod k 为 r 的个数的物品的方案数. 考虑朴素 \(dp\) ,定义状态 \(f[i][ ...

  4. bzoj 1009 [HNOI2008]GT考试——kmp+矩阵优化dp

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1009 首先想到 确保模式串不出现 就是 确保每个位置的后缀不是该模式串. 为了dp,需要记录 ...

  5. [Sdoi2017]序列计数 矩阵优化dp

    题目 https://www.lydsy.com/JudgeOnline/problem.php?id=4818 思路 先考虑没有质数限制 dp是在同余系下的,所以\(f[i][j]\)表示前i个点, ...

  6. 矩阵优化DP类问题应用向小结

    前言 本篇强调应用,矩阵的基本知识有所省略(也许会写篇基础向...). 思想及原理 为什么Oier们能够想到用矩阵来加速DP呢?做了一些DP题之后,我们会发现,有时候DP两两状态之间的转移是定向的,也 ...

  7. 洛谷P3193 GT考试 kmp+矩阵优化dp

    题意 求\(N\)位数字序列(可以有前导0)中不出现某\(M\)位子串的个数,模\(K\). \(N<=10^9,M<=20,K<=1000\) 分析 设\(dp[i][j]\)表示 ...

  8. $[TJOI2017]$ 可乐 矩阵优化$dp$

    \(Sol\) 设\(f_i\)为到第\(i\)秒的方案数,显然\(f_i=\)在第\(i\)秒前爆炸的方案数+在第\(i\)秒爆炸的方案数+在第\(i\)秒停下的方案数+在第\(i\)秒走向下一个城 ...

  9. bzoj 1096 斜率优化DP

    首先比较容易的看出来是DP,w[i]为前i个工厂的最小费用,那么w[i]=min(w[j-1]+cost(j,i))+c[i],但是这样是不work的,复杂度上明显过不去,这样我们考虑优化DP. 设A ...

随机推荐

  1. 大数加法(SDUT“斐波那契”串)4335

    题目链接:https://acm.sdut.edu.cn/onlinejudge2/index.php/Home/Contest/contestproblem/cid/2697/pid/4335.ht ...

  2. 在wamp下增加多版本的PHP(PHP5.3,PHP5.4,PHP5.5)支持

    1.安装WAMPServer 根据自己的操作系统选择相应的WAMP版本,我这里选择WAMPSERVER-32 BITS & PHP 5.5-2.5, 双击安装,选择安装目录即可,超级简单.根据 ...

  3. Delphi 10 seattle 去掉自带的代码连接线

  4. 190.Reverse Bits---位运算

    题目链接:https://leetcode.com/problems/reverse-bits/description/ 题目大意:将数值的二进制反转. 法一(借鉴):由于是无符号32位整型,当二进制 ...

  5. List基本用法

    List最为Collection接口的子接口,当然可以使用Collection接口里的全部方法.而且由于List是有序集合,因此List集合里增加了一些根据索引来操作集合元素的方法: public c ...

  6. Myeclipse编辑jsp文件很卡是什么原因?

    可能是配置问题,配置的时候不要把myeclipse连接到网络.否则每次编辑的时候要在网上查找,所以照成很卡.window->perferences->java->Installed ...

  7. BootStarp的form表单的基本写法

    代码如下: <!DOCTYPE html> <html> <head> <title>BootStrap的基础入门</title> < ...

  8. 解决IDEA导入Myclipse项目的时候没有识别为Web项目的问题

    IDEA在导入一个MyEclipse新建的Web项目的时候,一般会正确检测这个项目是什么项目.不过有时候会出现各种问题. 1. 出现一些Jar包不存在的问题,一般是servlet-api这样的包不存在 ...

  9. C语言俄罗斯方块

    #include <windows.h> #include <stdio.h> #include <time.h> #include <conio.h> ...

  10. centos6下mysql的主从复制的配置

    2015年9月17日 23:00:36 update 想要好好了解mysql复制,还是去看看<高性能MySQL>(第三版)好了,上面说的比较详细. =========== 在本地用virt ...