题面:求出满足以下条件的 n*m 的 01 矩阵个数:

    (1)第 i 行第 1~li 列恰好有 1 个 1 (li+1到ri-1不能放1)

    (2)第 i 行第 ri~m 列恰好有 1 个 1。

    (3)每列至多有 1 个 1

    对于 20%的数据,n,m<=12。

    对于 40%的数据,n,m<=50。

    对于 70%的数据,n,m<=300。

    对于 100%的数据,n,m<=3000,1<=li<ri<=m。

(考试前一天晚上玩过头了,整场考试直接划水,本题打了个状压,想不出来怎么优化就跳了)

 通过对题目的初步分析 本题是一类计数问题

  那么考虑这类问题解法通常为应用计数类DP或数学模型求解(本题显然DP色彩很浓厚)

然而 无论应用实际意义,数学模型都无法推出完整的式子 那么我们就需要思考DP类做法(事实上DP也是更为通用的做法)

  常规思考 问题状态有行,列,点 很容易想出状压DP的做法f[i][j]代表进行到第i行同时第i行状态为j

然而根据数据范围状压只能拿到20pts,显然不是正解 问题在于对于较大的m无法记录其状态 这样 直接否定了对行进行状压的过程

  思考问题在于枚举同一行点的状态的时间空间复杂度无法承受 那么为我们就要尽量降低这种复杂度

一种很显然的想法是既然我们不能记录同一行点的状态 那么缩小问题 记录单个点的状态的代价显然是能接受的

  那么思路逐渐清晰 我们需要考虑问题中行或列与节点的关系

一种常规DP设计手法是根据目标设计状态,阶段与决策 那么应用到本题上 目标是求n*m矩阵在一定条件下合法放置1的不同矩阵数

倒推分解问题 得 问题实际上是行或列放置1方案数的转移

  因此 设计状态f[i][j]表示已经进行到i列 其中有j列中的1放置在右区间,那么我们最终的目标就是f[m][n];

(这道题DP设计很新颖,思维量较高,然而其本质仍然是计数类DP的设计理念:通过精确划分使得状态各决策间满足加法原理 子状态间满足乘法原理(不重不漏))

显然本题状态划分是基于左右区间的互斥性 也就是说通过分别计算当前状态左右区间合法方案数来推出当前状态合法方案数

  很容易想到对于右区间 f[i][j] = f[i - 1][j] + f[i - 1] * (r[i] - (j - 1))  <1>  //其中r[i]代表右区间在i列及其以右的区间总数 l[i]同理

而有趣的是本题左右区间计算并不是完全独立的 相反 左区间的计算正是基于右区间已知的情况下进行的 (这为我们进行DP设计,具体到状态转移提供了新思路)

公式并不难推 f[i][j] = A(i - j - l[i - 1],l[i] - l[i - 1])  <2> ;最终根据乘法原理 状态f[i][j] = <1> * <2>;

  1. 1 #include<bits/stdc++.h>
  2. 2 using namespace std;
  3. 3 #define I int
  4. 4 #define LL long long
  5. 5 #define C char
  6. 6 #define RE register
  7. 7 #define L inline
  8. 8 const I mod = 998244353;
  9. 9 const I MAXN = 3050;
  10. 10 I n,m,l[MAXN],r[MAXN],j[MAXN],y[MAXN],f[MAXN][MAXN];
  11. 11 L I read(); L LL qpow(I,I); L LL A(I,I); L I getmin(I,I);
  12. 12 signed main(){
  13. 13 n = read(); m = read();j[0] = 1;f[0][0] = 1;
  14. 14 for(RE I i(1);i <= n; ++ i) ++l[read()],++r[read()];
  15. 15 for(RE I i(1);i <= m; ++ i) l[i] += l[i - 1],r[i] += r[i - 1];
  16. 16 for(RE I i(1);i <= m; ++ i) j[i] = 1ll * j[i - 1] * i % mod;
  17. 17 y[m] = qpow(j[m],mod - 2);
  18. 18 for(RE I i(m); i ; -- i) y[i - 1] = 1ll * y[i] * i % mod;
  19. 19 for(RE I i(1);i <= m; ++ i){
  20. 20 f[i][0] = 1ll * f[i - 1][0] * A(i - l[i - 1],l[i] - l[i - 1]) % mod;
  21. 21 for(RE I j(1);j <= getmin(n,i); ++ j)
  22. 22 f[i][j] = (f[i - 1][j] + 1ll * f[i - 1][j - 1] * (r[i] - j + 1)%mod) * A(i - j - l[i - 1],l[i] - l[i - 1]) % mod;
  23. 23 }printf("%d\n",f[m][n]);
  24. 24 }
  25. 25 L I read(){ RE I x(0); RE C z = getchar(); while(!isdigit(z)) z = getchar(); while(isdigit(z)) x = (x << 3) + (x << 1) + (z ^ 48),z = getchar(); return x; }
  26. 26 L LL qpow(I a,I b){
  27. 27 LL res(1),base(a);
  28. 28 while(b){
  29. 29 if(b & 1) res = 1ll * res * base % mod;
  30. 30 base = 1ll * base * base % mod;
  31. 31 b >>= 1;
  32. 32 }return res; }
  33. 33 L LL A(I n,I m){ if(m > n) return 0; return 1ll * j[n] * y[n - m] % mod; }
  34. 34 L I getmin(I a,I b){ return a < b ? a : b; }

总的来说本题真的是DP中一道精彩的问题 对于DP状态设计,决策都提供了较为新颖的思路 建议反复咀嚼

NOIP模拟5 T2的更多相关文章

  1. noip模拟6(T2更新

    由于蒟弱目前还没调出T1和T2,所以先写T3和T4.(T1T2更完辣! update in 6.12 07:19 T3 大佬 题目描述: 他发现katarina大佬真是太强了,于是就学习了一下kata ...

  2. NOIP 模拟4 T2

    本题属于二和一问题 子问题相互对称 考虑对于问题一:知a求b 那么根据b数组定义式 显然能发现问题在于如何求dis(最短路) 有很多算法可供选择 dijsktra,floyed,bfs/dfs,spf ...

  3. 20161003 NOIP 模拟赛 T2 解题报告

    Weed duyege的电脑上面已经长草了,经过辨认上面有金坷垃的痕迹. 为了查出真相,duyege 准备修好电脑之后再进行一次金坷垃的模拟实验. 电脑上面有若干层金坷垃,每次只能在上面撒上一层高度为 ...

  4. 20161023 NOIP 模拟赛 T2 解题报告

    Task 2.回文串计数 (calc.pas/calc.c/calc.cpp) [题目描述] 虽然是一名理科生,Mcx常常声称自己是一名真正的文科生.不知为何,他对于背诵总有一种莫名的热爱,这也促使他 ...

  5. 20161005 NOIP 模拟赛 T2 解题报告

    beautiful 2.1 题目描述 一个长度为 n 的序列,对于每个位置 i 的数 ai 都有一个优美值,其定义是:找到序列中最 长的一段 [l, r],满足 l ≤ i ≤ r,且 [l, r] ...

  6. 神奇的NOIP模拟赛 T2 LGTB 学分块

    LGTB 学分块 LGTB 最近在学分块,但是他太菜了,分的块数量太多他就混乱了,所以只能分成3 块今天他得到了一个数组,他突然也想把它分块,他想知道,把这个数组分成3 块,块可以为空.假设3 块各自 ...

  7. 2018.02.12 noip模拟赛T2

    二兵的赌注 Description游戏中,二兵要进入了一家奇怪的赌场.赌场中有n个庄家,每个庄家都可以猜大猜小,猜一次一元钱.每一次开彩前,你都可以到任意个庄家那里下赌注.如果开彩结果是大,你就可以得 ...

  8. ztz11的noip模拟赛T2:查房

    链接: https://www.luogu.org/problemnew/show/U46611 思路: 这道题告你n-1条边就是骗你的 部分分也是骗你的 这道题连对边5分钟的事 一个点对另一个点有影 ...

  9. 2018.10.30 NOIp模拟赛T2 数字对

    [题目描述] 小 H 是个善于思考的学生,现在她又在思考一个有关序列的问题.        她的面前浮现出一个长度为 n 的序列{ai},她想找出一段区间[L, R](1 <= L <= ...

  10. NOIP模拟18 T2

    不知道为什么很多人拒绝这题打搜索...其实搜索在充分剪枝后时间是非常优秀的,不管数据怎样基本都可跑出 首先一个显然结论:对于某种状态,他抓到的小精灵一定是一个连续的区间. 因此我们可以枚举这个区间的左 ...

随机推荐

  1. python3存储numpy格式的矩阵

    技术背景 numpy在python中的地位是相当高的,即使是入门的python使用者也会经常看到这个库的使用.除了替代python自带的列表数据格式list之外,numpy的一大优势是其底层的高性能实 ...

  2. Tomcat配置及网站创建教程(IDEA)

    Tomcat在本机的配置 解压 解压Tomcat压缩包后就算安装完成,解压完成生成文件夹 配置环境变量 1.配置JAVA_HOME 控制面板--系统--查看高级系统设置--环境变量--系统环境变量 新 ...

  3. 【Feign/Ribbon】记录一次生产上的SpringCloudFeign的重试问题

    在上周在的微供有数项目中(数据产品),需要对接企业微信中第三方应用,在使用Feign的去调用微服务的用户模块用微信的code获取access_token以及用户工厂信息时出现Feign重试超时报错的情 ...

  4. 从苏宁电器到卡巴斯基第14篇:我在苏宁电器当营业员 VI

    我也过了一把讲师的瘾 由于iPhone已经成为了我们的主推产品,因此苏宁要求手机专区的每一个人,不论是自营还是厂促,都要对iPhone非常了解才可以.于是,督导也没有事先通知我,就直接让我给手机专区的 ...

  5. <JVM下篇:性能监控与调优篇>补充:使用OQL语言查询对象信息

    笔记来源:尚硅谷JVM全套教程,百万播放,全网巅峰(宋红康详解java虚拟机) 同步更新:https://gitee.com/vectorx/NOTE_JVM https://codechina.cs ...

  6. PowerDesigner16安装和使用

    安装 安装参考链接:PowerDesigner安装教程 因为这个博主已经操作的很详细了,这边就不做过多的赘述. 使用 新建模型 选择物理模型 调出面板Palette 建表 最终的效果(一般不在数据库层 ...

  7. layui中流加载layui.flow

    1.引入layui.css和layui.js 2. html中定义容器 <div id="demo"></div> js部分: layui.use('flo ...

  8. css 实现三角形

    #demo1 { width: 0; height: 0; border-top: 100px solid rgba(255, 0, 0, 1); border-bottom: 50px solid ...

  9. K8s Scheduler 在调度 pod 过程中遗漏部分节点的问题排查

    问题现象 在TKE控制台上新建版本为v1.18.4(详细版本号 < v1.18.4-tke.5)的独立集群,其中,集群的节点信息如下: 有3个master node和1个worker node, ...

  10. Govern Service 基于 Redis 的服务治理平台

    Govern Service 基于 Redis 的服务治理平台(服务注册/发现 & 配置中心) Govern Service 是一个轻量级.低成本的服务注册.服务发现. 配置服务 SDK,通过 ...