题解 matrix
无比毒瘤的dp题,而且伪装地好像很可做的样子
考场上我给它氪了差不多一个小时最后还是只能扔了个20pts状压走人
以下思路基本均来源于题解:
对于此题,题面中三个限制条件:
(1)第 i 行第 1~li 列恰好有 1 个 1。 (li+1到ri-1不能放1)
(2)第 i 行第 ri~m 列恰好有 1 个 1。
(3)每列至多有 1 个 1。
根本注意不到注意到条件(3)相对比较好转移,所以此题考虑dp列而不是dp行
那么考虑从中选择一列该如何转移
显然每列只有放1或不放1两种情况,但条件(1)(2)在干扰我们转移
所以尝试消除干扰: 仅考虑单一区间(以右区间为例)
显然只有左端点到达这一列的区间需要被考虑
那么令\(dp[i][j]\)为从左到右第i列,所有跨越第i列的右区间中有j个已放过1
对于不放1的情况,\(dp[i][j] += dp[i-1][j]\)
对于放1,先定义数组\(cntl[i]\)为第i列及其左侧左区间的右端点的个数,\(cntr[i]\)同理
则第i列可以放1的左端点有\(cntr[i]-(j-1)\)个,所以\(dp[i][j] += dp[i-1][j-1]\times (cntr[i]-(j-1))\)
上面仅考虑了跨越第i列的右区间的方案数,那么下面处理左区间
首先定义\(f[i][j]\)时j指的是「所有跨越第i列的右区间中有j个已放过1」
那就不必考虑第i列的1应该给左区间还是右区间了
对于这种类似左右两边对抗的方案数dp
(就是说类似只能 在某条线以左/以右/以此线为分界左右同时 进行某种操作)
(为什么我一想到这就想起alpha-beta对抗搜索啊,好像将答案区间划分的思路差不多?)
考虑拆分区间,拆分出对左侧产生影响的右区间
则其对左区间影响已知,可计算出左区间
对于此题,i列左侧总共能放\(i-(j-1)\)个1,需要放\(cntl[i]-cntl[i-1]\)个
这个\(cntl[i]-cntl[i-1]\)其实是有多少个左区间在i位置结束,即「新增加的必须放1的区间个数」
是在满足i列以前必须放1的区间都满足的条件下转移
\(cntl[i]-cntl[i-1]\)个1放到\(i-(j-1)\)个行中,考虑不同方案,应该是排列数
所以\(dp[i][j] *= A^{cntl[i]-cntl[i-1]}_{i-(j-1)}\)
就可以转移了
一大坑点: 这类n, m混杂的题一定要分清n, m!我预处理阶乘逆元的时候习惯性打了i<=n直接调了一晚上最后还是战神帮忙指出来的谢谢战神小可爱啦大雾逃
Code:
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 3010
#define ll long long
#define ld long double
#define usd unsigned
#define ull unsigned long long
//#define int long long
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
char buf[1<<21], *p1=buf, *p2=buf;
inline int read() {
int ans=0, f=1; char c=getchar();
while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
return ans*f;
}
int n, m;
int l[N], r[N], lcnt[N], rcnt[N];
ll dp[N][N], fac[N], inv[N];
const ll mod=998244353;
inline ll A(ll n, ll k) {return fac[n]*inv[n-k]%mod;}
inline ll md(ll a) {return a>=mod?a-mod:a;}
signed main()
{
#ifdef DEBUG
freopen("1.in", "r", stdin);
#endif
n=read(); m=read();
if ((n<<1)>m) {puts("0"); return 0;}
for (int i=1; i<=n; ++i) l[i]=read(), r[i]=read();
sort(l+1, l+n+1); sort(r+1, r+n+1);
fac[0]=fac[1]=1; inv[0]=inv[1]=1;
for (int i=2; i<=m; ++i) fac[i]=fac[i-1]*i%mod;
for (int i=2; i<=m; ++i) inv[i]=(mod-mod/i)*inv[mod%i]%mod;
for (int i=2; i<=m; ++i) inv[i]=inv[i-1]*inv[i]%mod;
for (int i=1,p=1; i<=m; ++i) {rcnt[i]=rcnt[i-1]; while (p<=n&&r[p]==i) ++rcnt[i],++p;}
for (int i=1,p=1; i<=m; ++i) {lcnt[i]=lcnt[i-1]; while (p<=n&&l[p]==i) ++lcnt[i],++p;}
dp[0][0]=1;
for (int i=1; i<=m; ++i) {
dp[i][0] = dp[i-1][0]*A(i-lcnt[i-1], lcnt[i]-lcnt[i-1])%mod;
for (int j=1; j<=min(i, n); ++j)
dp[i][j] = md(dp[i-1][j]+dp[i-1][j-1]*max(rcnt[i]-(j-1), 0)%mod)*A(i-j-lcnt[i-1], lcnt[i]-lcnt[i-1])%mod; //, cout<<"A: "<<dp[i][j]<<endl;
}
printf("%lld\n", dp[m][n]);
return 0;
}
题解 matrix的更多相关文章
- 算法与数据结构基础 - 数组(Array)
数组基础 数组是最基础的数据结构,特点是O(1)时间读取任意下标元素,经常应用于排序(Sort).双指针(Two Pointers).二分查找(Binary Search).动态规划(DP)等算法.顺 ...
- [LeetCode 题解] Spiral Matrix
前言 [LeetCode 题解]系列传送门: http://www.cnblogs.com/double-win/category/573499.html 题目链接 54. Spiral Matrix ...
- 【题解】Sonya and Matrix Beauty [Codeforces1080E]
[题解]Sonya and Matrix Beauty [Codeforces1080E] 传送门:\(Sonya\) \(and\) \(Matrix\) \(Beauty\) \([CF1080E ...
- 【题解】#6622. 「THUPC 2019」找树 / findtree(Matrix Tree+FWT)
[题解]#6622. 「THUPC 2019」找树 / findtree(Matrix Tree+FWT) 之前做这道题不理解,有一点走火入魔了,甚至想要一本近世代数来看,然后通过人类智慧思考后发现, ...
- [题解]UVa 11082 Matrix Decompressing
开始眨眼一看怎么也不像是网络流的一道题,再怎么看也觉得像是搜索.不过虽然这道题数据范围很小,但也不至于搜索也是可以随随便便就可以过的.(不过这道题应该是special judge,因为一题可以多解而且 ...
- [LeetCode]题解(python):074-Search a 2D Matrix
题目来源 https://leetcode.com/problems/search-a-2d-matrix/ Write an efficient algorithm that searches fo ...
- [LeetCode]题解(python):059-Spiral Matrix II
题目来源 https://leetcode.com/problems/spiral-matrix-ii/ Given an integer n, generate a square matrix fi ...
- [LeetCode]题解(python):054-Spiral Matrix
题目来源 https://leetcode.com/problems/spiral-matrix/ Given a matrix of m x n elements (m rows, n column ...
- [LeetCode]题解(python):073-Set Matrix Zeroes
题目来源: https://leetcode.com/problems/set-matrix-zeroes/ 题意分析: 输入一个m×n矩阵,如果出现有0,那么将对应的行和列都变成0. 题目思路: 简 ...
随机推荐
- Adaptive AUTOSAR 学习笔记 3 - AP 背景、技术及特征(中文翻译)
本系列学习笔记基于 AUTOSAR Adaptive Platform 官方文档 R20-11 版本.本文从AUTOSAR_EXP_PlatformDesign.pdf开始,一边学习,一边顺带着翻译一 ...
- cke编辑器插入&ZeroWidthSpace占位字符的问题记录
背景 本博文主要记录在使用cke编辑器时,遇到的一系列的问题 问题1:在执行某些业务操作后,编辑器会偶现在页面头部或者尾部插入&ZeroWidthSpace占位符(编辑器好像就爱干这事~) 解 ...
- ESP32高分辨率计时器笔记
尽管FreeRTOS提供了软件计时器,但这些计时器有一些限制: 最大分辨率等于RTOS滴答周期 计时器回调从低优先级任务分派 硬件计时器不受这两个限制,但是通常它们使用起来不太方便.例如,应用组件可能 ...
- 『动善时』JMeter基础 — 55、JMeter非GUI模式运行
目录 1.JMeter的非GUI模式说明 2.为什么使用非GUI模式运行JMeter 3.怎样使用非GUI模式运行JMeter (1)非GUI模式运行JMeter步骤 (2)其它参数说明 4.CLI模 ...
- 前端-HTML基础+CSS基础
.pg-header { height: 48px; text-align: center; line-height: 48px; background-color: rgba(127, 255, 2 ...
- 一行代码打印python之禅
就这一句: import this 输出: The Zen of Python, by Tim Peters Beautiful is better than ugly. Explicit is be ...
- 00JAVA语法基础_四则运算 01
自动生成30道四则运算的数学题,当前只是简单符合出题,答题和判断的代码,还没做要求,所以现在只是能随机生成三十道100以内的加减法和九九乘法表的乘除法 package Sizeyunsuan; /** ...
- 论文阅读:LIC-Fusion: LiDAR-Inertial-Camera Odometry
本文提出了一种紧耦合的多传感器(雷达-惯导-相机)融合算法,将IMU测量.稀疏视觉特征.提取的激光点融合.提出的算法在时间和空间上对三个异步传感器进行在线校准,补偿校准发生的变化.贡献在于将检测和追踪 ...
- ClickHouse学习系列之八【数据导入迁移&同步】
背景 在介绍了一些ClickHouse相关的系列文章之后,大致对ClickHouse有了比较多的了解.它是一款非常优秀的OLAP数据库,为了更好的来展示其强大的OLAP能力,本文将介绍一些快速导入大量 ...
- 【Mysql】一个简易的索引方案
一.没有索引的时候如何查找 先忽略掉索引这个概念,如果现在直接要查某条记录,要如何查找呢? 在一个页中查找 如果表中的记录很少,一个页就够放,那么这时候有 2 种情况: 用主键为搜索条件:这时就是之前 ...