题目大意

用 \(p\) 种颜色填 \(n\times m\) 的画板,要求任意相邻两列的颜色数都不少于 \(q\) ,求方案数。

数据范围

\(1\leq n\leq 100,1\leq m\leq 10^9,q\leq p\leq 100\)

思路

观摩 \(m\) 的范围,显然需要一个 \(\log m\) 的做法,于是想到了矩阵快速幂。

首先考虑原始的转移。若当前一列涂上 \(j\) 种颜色,下一列要涂 \(k\) 种颜色,则方案数如下:

\[\sum \limits_{x=\max(q,j,k)}^{\min(p,j+k)}C_j^{j+k-x}C_{p-i}^{x-j}
\]

前一个组合数是 \(j\) 和 \(k\) 颜色中交集的部分,而后一个就是交集的补集。其中边界的意思分别为 \(j\cap k=\varnothing\) 和 \(j\subset k\) 或 \(k\subset j\)。意思就是说,这次的方案组成就是在满足条件的情况下,和上次相交的颜色的选择的方案乘上这次的新颜色的选择的方案。

然后对于每一列,定义 \(g[i][j]\),表示当前填到第 \(i\) 行的格子,涂 \(j\) 种颜色的方案数。则 \(g[n][j]\) 一列中涂 \(n\) 种颜色的方案。这个问题可以转化成有 \(j\) 个不同的盒子,要把 \(i\) 个不同的球放入盒子中,要求非空。这个问题就是第二类斯特林,递推式为:

\[g[i][j]=(g[i-1][j-1]+g[i-1][j])\times j
\]

即可以在放过球的盒子中再放一个,有 \(j\) 种,也可以新选一个没有放过球的盒子,这个新的盒子可以是 \(j\) 中的任何一个。因此一共 \(j\) 种。由于每一列的情况都是类似的,所以可以预处理出来。

那么转移矩阵就出来了。设 \(h[j][k]\) 表示这一列涂 \(j\) 种颜色,下一列涂 \(k\) 种颜色的方案数:

\[h[j][k]=g[n][j]\cdot\sum \limits_{x=\max(q,j,k)}^{\min(p,j+k)}C_j^{j+k-x}C_{p-i}^{x-j}
\]

则令 \(f[i][j]\) 为当前选到第 \(i\) 列,当前一列涂了 \(j\) 种颜色的方案数,则可以得到 \(f[i][j]=f[i-1][j]\times h[j][k]\),边界为 \(f[1][j]=g[n][j]\times C_p^j\),表示选 \(j\) 种颜色后涂上。由于 \(f\) 的转移系数与 \(i\) 无关,所以可以用矩阵快速幂优化转移 \(m-1\) 次后得到结果,时间复杂度 \(O(n^3\log m)\)。

代码

注意卡常。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=100+10;
const int Mod=998244353;
int n,m,p,q;
ll res;
ll C[maxn][maxn],g[maxn][maxn]; inline ll add(ll x,ll y){
if(x+y>Mod)return x+y-Mod;
return x+y;
} struct Mat{
ll a[maxn][maxn];
Mat(){
memset(a,0,sizeof(a));
}
inline void set(){
for(int i=1;i<=n;i++)
a[i][i]=1;
}
friend inline Mat operator *(register const Mat& A,register const Mat& B){
Mat C;
for(register int i=1;i<=p;i++)
for(register int j=1;j<=p;j++)
for(register int k=1;k<=p;k++)
C.a[i][j]=add(C.a[i][j],A.a[i][k]*B.a[k][j]%Mod);
return C;
}
}f,h; inline int read(){
int x=0;bool fopt=1;char ch=getchar();
for(;!isdigit(ch);ch=getchar())if(ch=='-')fopt=0;
for(;isdigit(ch);ch=getchar())x=(x<<3)+(x<<1)+ch-48;
return fopt?x:-x;
} inline Mat qpow(Mat x,int b){
Mat ans,base=x;
ans.set();
while(b){
if(b&1)ans=ans*base;
base=base*base;
b>>=1;
}
return ans;
} inline void Init(){
g[0][0]=C[0][0]=1;
for(int i=1;i<=100;i++){
C[i][0]=1;
for(int j=1;j<=i;j++)
C[i][j]=add(C[i-1][j],C[i-1][j-1]);
}
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
g[i][j]=add(g[i-1][j],g[i-1][j-1])*j%Mod;
} signed main(){
n=read();m=read();p=read();q=read();
Init();
for(register int j=1;j<=p;j++)
for(register int k=1;k<=p;k++){
int l=max(max(q,j),k),r=min(p,j+k);
for(register int i=l;i<=r;i++)
h.a[j][k]=add(h.a[j][k],C[j][j+k-i]*C[p-j][i-j]%Mod);
h.a[j][k]=h.a[j][k]*g[n][k]%Mod;
}
f=qpow(h,m-1);
for(register int i=1;i<=p;i++)
for(register int j=1;j<=p;j++)
res=add(res,f.a[i][j]*C[p][i]%Mod*g[n][i]%Mod);//简单易懂的求和
printf("%lld\n",res);
return 0;
}

【矩阵乘优化DP】涂色游戏的更多相关文章

  1. CodeForces621E 快速矩阵幂优化dp

    有时些候在用快速矩阵幂优化dp的时候,它的矩阵乘法是不那么容易被具体为题目背景的意思的,大多数时候难以理解矩阵之间相乘的实际意义,正如有时候我们不知道现在在做手头这些事情的意义,但倘若是因一个目标而去 ...

  2. 形态形成场(矩阵乘法优化dp)

    形态形成场(矩阵乘法优化dp) 短信中将会涉及前\(k\)种大写字母,每个大写字母都有一个对应的替换式\(Si\),替换式中只会出现大写字母和数字,比如\(A→BB,B→CC0,C→123\),代表 ...

  3. 斐波那契数列 矩阵乘法优化DP

    斐波那契数列 矩阵乘法优化DP 求\(f(n) \%1000000007​\),\(n\le 10^{18}​\) 矩阵乘法:\(i\times k\)的矩阵\(A\)乘\(k\times j\)的矩 ...

  4. [CSP-S模拟测试]:涂色游戏(DP+组合数+矩阵快速幂)

    题目描述 小$A$和小$B$在做游戏.他们找到了一个$n$行$m$列呈网格状的画板.小$A$拿出了$p$支不同颜色的画笔,开始在上面涂色.看到小$A$涂好的画板,小$B$觉得颜色太单调了,于是把画板擦 ...

  5. NOIp十连测 涂色游戏

    [问题描述]小A 和小B 在做游戏.他们找到了一个n 行m 列呈网格状的画板.小A 拿出了p 支不同颜色的画笔,开始在上面涂色.看到小A 涂好的画板,小B 觉得颜色太单调了,于是把画板擦干净,希望涂上 ...

  6. hdu 4559 涂色游戏(对SG函数的深入理解,推导打SG表)

    提议分析: 1 <= N <= 4747 很明显应该不会有规律的,打表发现真没有 按题意应该分成两种情况考虑,然后求其异或(SG函数性质) (1)找出单独的一个(一列中只有一个) (2)找 ...

  7. [BZOJ 1009] [HNOI2008] GT考试 【AC自动机 + 矩阵乘法优化DP】

    题目链接:BZOJ - 1009 题目分析 题目要求求出不包含给定字符串的长度为 n 的字符串的数量. 既然这样,应该就是 KMP + DP ,用 f[i][j] 表示长度为 i ,匹配到模式串第 j ...

  8. 矩阵乘法优化DP

    本文讲一下一些基本的矩阵优化DP的方法技巧. 定义三个矩阵A,B,C,其中行和列分别为$m\times n,n \times p,m\times p$,(其中行是从上往下数的,列是从左往右数的) $C ...

  9. hdu 4559 涂色游戏(SG)

    在一个2*N的格子上,Alice和Bob又开始了新游戏之旅. 这些格子中的一些已经被涂过色,Alice和Bob轮流在这些格子里进行涂色操作,使用两种涂色工具,第一种可以涂色任意一个格子,第二种可以涂色 ...

  10. 【循环矩阵乘优化DP】BZOJ 2510 弱题

    题目大意 有 \(M\) 个球,一开始每个球均有一个初始标号,标号范围为 \(1\) - \(N\) 且为整数,标号为 \(i\) 的球有 \(a_i\) 个,并保证 \(\sum a_i = M\) ...

随机推荐

  1. Oracle数据库之体系结构

    Oracle数据库管理系统中的3个重要的概念:实例(Instance).数据库(Database)和数据库服务器(Database Server). 实例:是后台进程和内存结构的集合,是Oracle数 ...

  2. 设计模式也可以这么简单(7年开发老鸟PS注释总结)

    设计模式是对大家实际工作中写的各种代码进行高层次抽象的总结,其中最出名的当属 Gang of Four (GoF) 的分类了,他们将设计模式分类为 23 种经典的模式,根据用途我们又可以分为三大类,分 ...

  3. oracle之二数据库审计

    数据库审计audit(PPT-I-320-334) 13.1 审计的功能:监控特定用户在database 的action(操作) 13.2 审计种类: 1)标准数据库审计(语句审计.权限审计.对象审计 ...

  4. WeihanLi.Npoi 1.10.0 更新日志

    WeihanLi.Npoi 1.10.0 更新日志 Intro 上周有个网友希望能够导入Excel时提供一个 EndRowIndex 来自己控制结束行和根据字段过滤的,周末找时间做了一下这个 feat ...

  5. HTML自学第一篇

    教程来自W3CSchool 因为笔者有过开发经验 本篇只是个人对HTML自学的笔记,可能不适合用于给他人理解和学习 什么是 HTML HTML 指的是超文本标记语言 (Hyper Text Marku ...

  6. Mysql-Innodb : 从一个字节到整个数据库表了解物理存储结构和逻辑存储结构

    首先要从Innodb怎么看待磁盘物理空间说起   一块原生的(Raw)物理磁盘,可以把他看成一个字节一个字节单元组成的物理存储介质   如果要在这块原生物理空间中插入一条记录,不能单单只插入数据,还需 ...

  7. 快速了解前端开发HTML的正确姿势

    摘要:web前端开发(也称为客户端开发)主要是通过html,CSS和JavaScript等前端技术,实现网站在客服端的正确显示及交互功能. 一.web标准介绍 web标准: w3c:万维网联盟组织,用 ...

  8. XDCMS审计(复现)

    最近开始学习审计,拿一些简单cms的漏洞复现一下.源码在文末会分享出来. 0x01 index.php <?php if(!file_exists("data/config.inc.p ...

  9. Redis报错“ OOM command not allowed when used memory > 'maxmemory' ”

    生产环境上遇到这个问题,控制台不停打印 "OOM command not allowed when used memory > 'maxmemory' "; 起初不知道是什么 ...

  10. Vue 表单拖拽排序

    Vue table表单拖拽 业务需求: 因为数据展示使用的是 elementUI 的 Table进行数据展示的,现在的需求是通过拖拽表单进行表单排序.同时,动态修改表单中的数据排列顺序.查阅了好多资料 ...