BZOJ5416 NOI2018冒泡排序(动态规划+组合数学)
打表可以发现相当于不存在长度>=3的递减子序列。
考虑枚举在哪一位第一次不卡限制。注意到该位一定会作为前缀最大值。判掉已确定位不合法的情况后,现在的问题即为求长度为i、首位>j的合法排列个数,设其为g[i][j]。
由于首位>j,1~j在排列中一定依次出现,并且在j出现之前,>j的部分也一定单增。于是可以先将>j的部分安排好,再将1~j不改变相对顺序地插入。>j的部分即是考虑没有各种奇怪的限制要怎么求。设f[i][j]为长度i的排列,第一个非前缀max的数在j位置的方案数。特别地,令f[i][i+1]为不存在这样的数时的方案数(当然就是1)。则有f[i][j]=Σf[i-1][k] (j-1<=k<=i+1),也即f[i][j]=f[i][j+1]+f[i-1][j-1]。这样f[i][1~i+1]即为n=i且无限制的答案,并且有了这个求g就很容易了,即考虑1~j的插入位置,有g[i][j]=Σf[i-j][k]·C(j+k-2,k-2) (k=2~i-j+1)。于是得到了一个80分的做法。给无限制时的答案打一下表又可以发现答案即为卡特兰数,可以再拿4分。
似乎有点陷入僵局。继续打表!我们惊奇的发现,g[i][j]=f[i+1][j+3]。这个式子可能是说明之前绕了太多弯,本来直接考虑怎么推g就行了,虽然这个我没想清楚也懒得考虑了。由于最终要用到的只是g中的n项,如果能快速求出f数组中任意项,问题就解决了。
考虑根据f的转移方程画一张有向图,答案即为由原点走到目标点的路径条数。
得到这样一个丑陋的图。如果要到最左的点,就是卡特兰数的经典模型。于是下面所有的分析只要类比卡特兰数就可以了。事实上这是个原题https://www.luogu.org/problemnew/show/P1641。
考虑先不管图的边界随便走,此时向右下走n步、向左走m步时的方案数显然是C(n+m,m)。加上边界后,考虑哪些走法会变得不合法,显然不合法的方案中一定存在一个第一次跨过边界的点,而这可以看做是从左上一个并不存在的点(原点向左平移两格)、以边界为对称轴、按和右边对称的走法走来的,经过此点后走法变为和右边相同。并且显然每一种从这个不存在的点到达终点的走法都对应于一种不合法方案。两个组合数相减即可。原问题也被线性解决了。
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
#define P 998244353
#define N 600010
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<''||c>'')) c=getchar();return c;}
int gcd(int n,int m){return m==?n:gcd(m,n%m);}
int read()
{
int x=,f=;char c=getchar();
while (c<''||c>'') {if (c=='-') f=-;c=getchar();}
while (c>=''&&c<='') x=(x<<)+(x<<)+(c^),c=getchar();
return x*f;
}
int T,n,a[N],fac[N<<],inv[N<<],mn[N],ans;
int C(int n,int m){if (m<) return ;return 1ll*fac[n]*inv[m]%P*inv[n-m]%P;}
int calc(int n,int m){m=n-m;return (C(n+m,m)-C(n+m,m-)+P)%P;}
int main()
{
#ifndef ONLINE_JUDGE
freopen("bzoj5416.in","r",stdin);
freopen("bzoj5416.out","w",stdout);
const char LL[]="%I64d\n";
#else
const char LL[]="%lld\n";
#endif
T=read();
while (T--)
{
n=read();
for (int i=;i<=n;i++) a[i]=read();
fac[]=;for (int i=;i<=*n;i++) fac[i]=1ll*fac[i-]*i%P;
inv[]=inv[]=;for (int i=;i<=*n;i++) inv[i]=P-1ll*(P/i)*inv[P%i]%P;
for (int i=;i<=*n;i++) inv[i]=1ll*inv[i-]*inv[i]%P;
int mx=;ans=;
mn[n+]=n+;
for (int i=n;i>=;i--) mn[i]=min(mn[i+],a[i]);
for (int i=;i<=n;i++)
{
mx=max(mx,a[i]);
ans=(ans+calc(n-i+,mx-i+))%P;
if (a[i]<mx&&a[i]>mn[i+]) break;
}
printf("%d\n",ans);
}
return ;
}
BZOJ5416 NOI2018冒泡排序(动态规划+组合数学)的更多相关文章
- BZOJ_5416_[Noi2018]冒泡排序_DP+组合数+树状数组
BZOJ_5416_[Noi2018]冒泡排序_DP+组合数+树状数组 Description www.lydsy.com/JudgeOnline/upload/noi2018day1.pdf 好题. ...
- 【洛谷4769】[NOI2018] 冒泡排序(动态规划_组合数学)
题目: 洛谷 4769 博客页面左下角的嘴嘴瓜封神之战中的题目 分析: 一个排列交换次数为 \(\frac{1}{2}\sum_{i=1}^{n}|i-p_i|\) 的充要条件是这个排列不存在长度为 ...
- [NOI2018]冒泡排序
https://www.zybuluo.com/ysner/note/1261482 题面 戳我 \(8pts\ n\leq9\) \(44pts\ n\leq18\) \(ex12pts\ q_i= ...
- 【NOI 2018】冒泡排序(组合数学)
题意大概是给定一个长度为$n$的排列$p$,求有多少长度为$n$的排列满足冒泡排序的交换次数为$\frac{1}{2} \sum\limits_{i = 1}^{n}|i - p_{i}|$. 可以发 ...
- [POJ1664] 放苹果 (动态规划,组合数学)
题目描述 把M个同样的苹果放在N个同样的盘子里,允许有的盘子空着不放,问共有多少种不同的分发(5,1,1和1,1,5是同一种方法) 输入输出格式 输入格式: 第一行是测试数据的数目t(0 <= ...
- 【UOJ#394】[NOI2018] 冒泡排序
题目链接 题意 求有多少个字典序严格大于给定排列 \(q_i\) 的排列满足其逆序对数(冒泡排序需要交换的次数)达到下限 \(\frac{1}{2}\sum_{i=1}^n |i-p_i|\) Sol ...
- luogu P4769 [NOI2018]冒泡排序 结论 树状数组 卡特兰数
LINK:冒泡排序 神题. 可以想到爆搜 期望得分5~10分. 打成这个样子心态不得爆炸? 仔细分析 一个不合法序列还有什么标志. 容易想到某个数字离自己位置相反的方向多走了一步. 考虑单独对每个数字 ...
- Codeforces 979E Kuro and Topological Parity - 动态规划 - 组合数学
题目传送门 传送点 题目大意 给定$n$个标号依次为$1, 2, \cdots, n$的点,其中一些点被染成一些颜色,剩下的点没有染色.你需要添加一些有向边并将剩下的点染色,满足有向边从编号小的一端指 ...
- BZOJ2339 HNOI2011卡农(动态规划+组合数学)
考虑有序选择各子集,最后除以m!即可.设f[i]为选i个子集的合法方案数. 对f[i]考虑容斥,先只满足所有元素出现次数为偶数.确定前i-1个子集后第i个子集是确定的,那么方案数为A(2n-1,i-1 ...
随机推荐
- jquery mouseover与mouseenter区别
<!DOCTYPE html> <html lang="en" xmlns="http://www.w3.org/1999/xhtml"> ...
- js中常见继承方式
1.原型模式 function Father(){ this.property = true; } Father.prototype.getValue = function(){ return thi ...
- Go语言安全编码规范-翻译(分享转发)
Go语言安全编码规范-翻译 本文翻译原文由:blood_zer0.Lingfighting完成 如果翻译的有问题:联系我(Lzero2012).匆忙翻译肯定会有很多错误,欢迎大家一起讨论Go语言安全能 ...
- Selenium 爬取全国水质周报Word
很久没写爬虫了 ,昨天有个学姐说需要爬取水质的一些数据,给了个网站( http://xxfb.hydroinfo.gov.cn/ssIndex.html?type=2&tdsourcetag= ...
- metasploit-smb扫描获取系统信息
1.msfconsle 2.use auxiliary/scanner/smb/smb_version 3. msf auxiliary(smb_version) > set RHOSTS 17 ...
- libgdx学习记录17——照相机Camera
照相机在libgdx中的地位举足轻重,贯穿于整个游戏开发过程的始终.一般我们都通过Stage封装而间接使用Camera,同时我们也可以单独使用Camera以完成背景的移动.元素的放大.旋转等操作. C ...
- SSIS 组件属性整理
整理SSIS 组件的属性解释及其用法 一,ExecValueVariable属性 有些Task组件执行完成之后,会产生输出结果,称作Execution Value,例如,Execute SQL Tas ...
- .Net Core WebApi控制器接收原始请求正文内容
主要目标 在Asp.net Core控制器中,通过自定义格式化程序来映射自定义处理控制器中的“未知”内容. 简单案例 为了演示这个问题,我们用VS2017创建一个默认的Asp.net Core Web ...
- docker之容器管理
一.docker常用的创建命令 [root@node03 ~]# docker create --help [root@node03 ~]# docker run --help OPTIONS说明: ...
- Mysql的基本操作(一)增、删、改
创建/增加(create创建,alter字段操作,insert插入) 创建数据库 create database 数据库名称 charset=utf8; # 例: create database te ...