【矩阵乘优化DP】涂色游戏
题目大意
用 \(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\) 种颜色,则方案数如下:
\]
前一个组合数是 \(j\) 和 \(k\) 颜色中交集的部分,而后一个就是交集的补集。其中边界的意思分别为 \(j\cap k=\varnothing\) 和 \(j\subset k\) 或 \(k\subset j\)。意思就是说,这次的方案组成就是在满足条件的情况下,和上次相交的颜色的选择的方案乘上这次的新颜色的选择的方案。
然后对于每一列,定义 \(g[i][j]\),表示当前填到第 \(i\) 行的格子,涂 \(j\) 种颜色的方案数。则 \(g[n][j]\) 一列中涂 \(n\) 种颜色的方案。这个问题可以转化成有 \(j\) 个不同的盒子,要把 \(i\) 个不同的球放入盒子中,要求非空。这个问题就是第二类斯特林,递推式为:
\]
即可以在放过球的盒子中再放一个,有 \(j\) 种,也可以新选一个没有放过球的盒子,这个新的盒子可以是 \(j\) 中的任何一个。因此一共 \(j\) 种。由于每一列的情况都是类似的,所以可以预处理出来。
那么转移矩阵就出来了。设 \(h[j][k]\) 表示这一列涂 \(j\) 种颜色,下一列涂 \(k\) 种颜色的方案数:
\]
则令 \(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】涂色游戏的更多相关文章
- CodeForces621E 快速矩阵幂优化dp
有时些候在用快速矩阵幂优化dp的时候,它的矩阵乘法是不那么容易被具体为题目背景的意思的,大多数时候难以理解矩阵之间相乘的实际意义,正如有时候我们不知道现在在做手头这些事情的意义,但倘若是因一个目标而去 ...
- 形态形成场(矩阵乘法优化dp)
形态形成场(矩阵乘法优化dp) 短信中将会涉及前\(k\)种大写字母,每个大写字母都有一个对应的替换式\(Si\),替换式中只会出现大写字母和数字,比如\(A→BB,B→CC0,C→123\),代表 ...
- 斐波那契数列 矩阵乘法优化DP
斐波那契数列 矩阵乘法优化DP 求\(f(n) \%1000000007\),\(n\le 10^{18}\) 矩阵乘法:\(i\times k\)的矩阵\(A\)乘\(k\times j\)的矩 ...
- [CSP-S模拟测试]:涂色游戏(DP+组合数+矩阵快速幂)
题目描述 小$A$和小$B$在做游戏.他们找到了一个$n$行$m$列呈网格状的画板.小$A$拿出了$p$支不同颜色的画笔,开始在上面涂色.看到小$A$涂好的画板,小$B$觉得颜色太单调了,于是把画板擦 ...
- NOIp十连测 涂色游戏
[问题描述]小A 和小B 在做游戏.他们找到了一个n 行m 列呈网格状的画板.小A 拿出了p 支不同颜色的画笔,开始在上面涂色.看到小A 涂好的画板,小B 觉得颜色太单调了,于是把画板擦干净,希望涂上 ...
- hdu 4559 涂色游戏(对SG函数的深入理解,推导打SG表)
提议分析: 1 <= N <= 4747 很明显应该不会有规律的,打表发现真没有 按题意应该分成两种情况考虑,然后求其异或(SG函数性质) (1)找出单独的一个(一列中只有一个) (2)找 ...
- [BZOJ 1009] [HNOI2008] GT考试 【AC自动机 + 矩阵乘法优化DP】
题目链接:BZOJ - 1009 题目分析 题目要求求出不包含给定字符串的长度为 n 的字符串的数量. 既然这样,应该就是 KMP + DP ,用 f[i][j] 表示长度为 i ,匹配到模式串第 j ...
- 矩阵乘法优化DP
本文讲一下一些基本的矩阵优化DP的方法技巧. 定义三个矩阵A,B,C,其中行和列分别为$m\times n,n \times p,m\times p$,(其中行是从上往下数的,列是从左往右数的) $C ...
- hdu 4559 涂色游戏(SG)
在一个2*N的格子上,Alice和Bob又开始了新游戏之旅. 这些格子中的一些已经被涂过色,Alice和Bob轮流在这些格子里进行涂色操作,使用两种涂色工具,第一种可以涂色任意一个格子,第二种可以涂色 ...
- 【循环矩阵乘优化DP】BZOJ 2510 弱题
题目大意 有 \(M\) 个球,一开始每个球均有一个初始标号,标号范围为 \(1\) - \(N\) 且为整数,标号为 \(i\) 的球有 \(a_i\) 个,并保证 \(\sum a_i = M\) ...
随机推荐
- 9.下载ffmpeg、使QT支持同时编译32位和64位
1.FFMPEG下载 进入http://ffmpeg.org/download.html,如果下载源码,则在右下方: 如果在linux中,直接输入git clone https://git.ffmpe ...
- layui表单引入ueditor遇坑记
1. 错误示例:表单容器是div标签则无法获取ueditor的内容 注:对于普通的表单元素表单容器是div也都能获取 <!DOCTYPE html> <html> <he ...
- YOLOv4: Darknet 如何于 Docker 编译,及训练 COCO 子集
YOLO 算法是非常著名的目标检测算法.从其全称 You Only Look Once: Unified, Real-Time Object Detection ,可以看出它的特性: Look Onc ...
- npm 报错 cb.apply is not a function
解决方法1 目录C:\Users(your username)\AppData\Roaming 有个npm文件夹 删除如果没有 npm cache文件cmd下运行 npm clean cache —f ...
- webstorm中emmet展开a标签和行内元素不换行的解决办法
大家好我是木瓜太香,大家在使用 webstorm 编写 html 的时候可能会遇到展开部分标签挨在一起的情况,相信很多小伙伴都想解决这个问题,接下来我们就开始吧! 先来看看我们输入如下 emmet 代 ...
- 解决IDEA打包出现中文乱码的问题
这主要是maven编译时编码问题导致的. 解决办法: 1.在IDEA的File里面打开Settings. 2.找到Runner,在VM Options输入-DarchetypeCatalog=inte ...
- 高可用集群之keepalived+lvs实战
keepalived简介 lvs在我之前的博客<高负载集群实战之lvs负载均衡-技术流ken>中已经进行了详细的介绍和应用,在这里就不再赘述.这篇博文将把lvs与keepalived相结合 ...
- 剑指offer 59-II 队列的最大值
题目描述 请定义一个队列并实现函数 max_value 得到队列里的最大值,要求函数max_value.push_back 和 pop_front 的均摊时间复杂度都是O(1). 若队列为空,pop_ ...
- EAM资产管理系统应用趋势简述
EAM资产管理系统应用趋势简述 随着各种企业对资产管理需求的不断增长,EAM市场也正在持续升温,对于石油.化工.煤炭.钢铁等流程化企业及其他资产密集型企业来说,设备占用了企业大量的成本,如何降低设备维 ...
- golang 协程学习
协程数据传递问题 func TestGoroutineData(t *testing.T) { var wg sync.WaitGroup wg.Add(1) i := 0 go func(j int ...