我的第一道需要程序建矩阵的矩阵优化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. 多进程Process

    多进程旧式写法 from multiprocessing import Pool def f(x): return x*x if __name__ == '__main__': p = Pool(5) ...

  2. inet_confirm_addr && confirm_addr_indev

    确认给定参数范围的ip地址是否存在: /* * Confirm that local IP address exists using wildcards: * - net: netns to chec ...

  3. /proc/sys 子目录的作用

    该子目录的作用是报告各种不同的内核参数,并让您能交互地更改其中的某些.与 /proc 中所有其他文件不同,该目录中的某些文件可以写入,不过这仅针对 root. 其中的目录以及文件的详细列表将占据过多的 ...

  4. AspNet Core 发布到Linux系统和发布IIS 注意项

    AspNet Core 发布到Linux系统和发布IIS 注意项 1.发布时需要注意的 2.Windows Server 2012 api-ms-win-crt-runtime-l1-1-0.dll ...

  5. ireport报表制作, 通过节点、产品类型来判断,当该节点审核通过之后,报表相对应的审核意见及签名 显示相对应的内容

    1.代码①  (与本内容相关的代码:7~36)           以下类似 $P{P_XXXX} :均为页面端的传入参数 select so.sale_order_no as sale_order_ ...

  6. Python股票信息抓取~

    本来想把股票的涨跌抓取出来,用汇通网的股票为例,就找了国际外汇为例. 页面里有xhr请求,并且每个xhr的url请求的 http://api.q.fx678.com/history.php?symbo ...

  7. 数据分析python应用到的ggplot

    数据分析中应用到python中的ggplot库,可以用来画图 数据之类的用优达学院中课程七中的数据为例 数据是:https://s3.amazonaws.com/content.udacity-dat ...

  8. C语言实现knn

    以后写代码一定要谨慎,提高代码的正确率. /*************************************** * 1.初始化距离为最大值 * 2.计算未知样本和每个训练样本的距离为dis ...

  9. Jmeter中的变量(三)

    变量(Variables) Jmeter中的变量(参数化)目的是为了提供改变请求变化的机制.比如登录场景,一般不能使用同一个账号做并发操作. 变量的特点 1) JMeter变量对于测试线程而言是局部变 ...

  10. 深度学习方法(十三):卷积神经网络结构变化——可变形卷积网络deformable convolutional networks

    上一篇我们介绍了:深度学习方法(十二):卷积神经网络结构变化--Spatial Transformer Networks,STN创造性地在CNN结构中装入了一个可学习的仿射变换,目的是增加CNN的旋转 ...