【矩阵乘优化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\) ...
随机推荐
- 浅谈DOM事件的优化
在 JavaScript 程序的开发中,经常会用到一些频繁触发的 DOM 事件,如 mousemove.resize,还有不是那么常用的鼠标滚轮事件:mousewheel (在 Firefox 中,滚 ...
- [算法题]最小m划分(划分DP)
题目描述 给定 n 个整数组成的序列,将序列分割为 m 段,如何分割才能使这 m 段子序列的和的最大值达到最小? 题解 状态表示 dp[i][j]表示前i个元素划分j段 子序列和的最大值的最小值 状态 ...
- JWT理论理解
什么是JWT Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准(RFC 7519).该token被设计为紧凑且安全的,特别适用于分布式站点的 ...
- 基于k8s的集群稳定架构
前言 我司的集群时刻处于崩溃的边缘,通过近三个月的掌握,发现我司的集群不稳定的原因有以下几点: 1.发版流程不稳定 2.缺少监控平台[最重要的原因] 3.缺少日志系统 4.极度缺少有关操作文档 5.请 ...
- MySql基础_DDL_DML_DQL(资料一)
今日内容 数据库的基本概念 MySQL数据库软件 安装 卸载 配置 SQL 数据库的基本概念 1. 数据库的英文单词: DataBase 简称 : DB 2. 什么数据库? * 用于存储和管理数据的仓 ...
- 深入理解SVM,详解SMO算法
今天是机器学习专题第35篇文章,我们继续SVM模型的原理,今天我们来讲解的是SMO算法. 公式回顾 在之前的文章当中我们对硬间隔以及软间隔问题都进行了分析和公式推导,我们发现软间隔和硬间隔的形式非常接 ...
- myisamchk是用来做什么的?MyISAM Static和MyISAM Dynamic有什么区别?
myisamchk是用来做什么的? 它用来压缩MyISAM[歌1] 表,这减少了磁盘或内存使用. MyISAM Static和MyISAM Dynamic有什么区别? 在MyISAM Static上的 ...
- 实践案例丨利用小熊派开发板获取土壤湿度传感器的ADC值
摘要:一文带你用小熊派开发板动手做土壤湿度传感器. 一.实验准备 1.实验环境 一块stm32开发板(推荐使用小熊派),以及数据线 已经安装STM32CubeMX 已经安装KeilMDK,并导入stm ...
- 我没学过计算机,是怎么接了四个私活还挣了两个 iPad 的?
你好,我是悟空哥,「7年项目开发经验,全栈工程师,开发组长,超喜欢图解编程底层原理」.我还手写了2个小程序,Java刷题小程序,PMP刷题小程序.我的 GitHub. 前言 大家看到这篇文章的时候,我 ...
- Java知识系统回顾整理01基础01第一个程序04创建Eclipse项目
一.为Eclipse设置桌面快捷方式图标 二.双击桌面快捷方式打开Eclipse 三.选择工作区 使用在命令行Hello World中的项目目录e:\project 除了第一次启动eclipse的时候 ...