【题解】有限制的排列 [51nod1296]

传送门:有限制的排列 \([51nod1296]\)

【题目描述】

给出 \(n,m_1,m_2\) 和 \(\{a[1],a[2]...a[m_1]\},\{b[1],b[2]...b[m_2]\}\)

计算整数 \([1,n]\) 满足以下条件的排列个数:

位置 \(a[i]\) \((i \in [1,m_1])\) 上的数均小于其邻居,位置 \(b[i]\) \((i \in [1,m_2])\) 上的数均大于其邻居(位置编号从 \(0\) 开始)。

答案对 \(1e9+7\) 取模。

如样例:

\(N=4,a=\{1\},b=\{2\}\),符合条件的排列有:

\(2,1,4,3\)

\(3,2,4,1\)

\(4,2,3,1\)

\(3,1,4,2\)

\(4,1,3,2\)

答案为 \(5\) 。

【样例】

样例输入:
4 1 1
1
2 样例输出:
5

【数据范围】

\(100\%\) \(1 \leqslant n \leqslant 5000,\) \(1 \leqslant m_1,m_2 \leqslant n\)


【分析】

一道 \(dp\) 题,要维护的关键信息在于相邻数字的大小关系,用 \(dp[i][j]\) 表示整数 \([1,i]\) 满足要求的排列中,最后一个数选 \(a[i]=j\) 的排列数量。

为了方便状态的转移,只记录每个数和前一个数相比需要满足的大小关系。

开一个数组 \(p\):

\(p[i]=0\) : \(a[i]\) 无限制,\(dp[i][j]=\sum_{k=1}^{i-1} dp[i-1][k]\)

\(p[i]=1\) : \(a[i]\) 要小于 \(a[i-1]\),\(dp[i][j]=\sum_{k=j}^{i-1} dp[i-1][k]\)

\(p[i]=2\) : \(a[i]\) 要大于 \(a[i-1]\),\(dp[i][j]=\sum_{k=1}^{j-1} dp[i-1][k]\)

通常的理解是直接在已选好的序列后面加入了一个 \(j\),但并不能保证 \(j\) 在前面一定没有出现过,所以要理解为:把前面已选好的序列中大于等于 \(j\) 的数都加一后再把 \(j\) 加到后面。

所以当 \(p[i]=1\) 时,\(k\) 的下边界是 \(j\) 而不是 \(j+1\)(单纯的理解为结尾比 \(j\) 大的情况),因为当 \(a[i-1]\) 为 \(j\) 时,加了 \(1\) 之后就大于 \(j\) 了,此时 \(a[i]\) 恰好可为 \(j\) 。

而当 \(p[i]=2\) 时,\(k\) 的上边界却不能取到 \(j\),如果取到了 \(j\),那么 \(j+1\) 就会大于 \(j\),即 \(a[i-1] > a[i]\),该种排列与限制关系矛盾。

求和的过程可以用前缀和省略掉,初始化为 \(dp[1][1]=S[1]\) (\(dp[1]=1\) 为的是防止出现 \(n=1\) 这样的奇葩数据)。

时间复杂度:\(O(n^2)\) 。


【Code】

#include<algorithm>
#include<cstdio>
#include<queue>
#define Re register int
const int N=5003,P=1e9+7;
int x,n,m1,m2,ans,p[N],S[N],dp[N][N];
//p[i]=0 无限制
//p[i]=1 a[i-1]>a[i]
//p[i]=2 a[i-1]<a[i]
inline void in(Re &x){
int f=0;x=0;char c=getchar();
while(c<'0'||c>'9')f|=c=='-',c=getchar();
while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c^48),c=getchar();
x=f?-x:x;
}
int main(){
in(n),in(m1),in(m2);
while(m1--)in(x),++x,p[x]=1,p[x+1]=2;
while(m2--)in(x),++x,p[x]=2,p[x+1]=1;
dp[1][1]=S[1]=1;
for(Re i=2;i<=n;++i){
for(Re j=1;j<=i;++j){
if(!p[i])(dp[i][j]+=S[i-1])%=P;
else if(p[i]<2)(dp[i][j]+=(S[i-1]-S[j-1]+P)%P)%=P;
else (dp[i][j]+=S[j-1])%=P;
}
for(Re j=1;j<=i;++j)S[j]=(S[j-1]+dp[i][j])%P;
}
for(Re i=1;i<=n;++i)(ans+=dp[n][i])%=P;
printf("%d",ans);
}

【题解】有限制的排列 [51nod1296]的更多相关文章

  1. 【题解】逆序排列 [51nod1020]

    [题解]逆序排列 [51nod1020] 传送门:逆序排列 \([51nod1020]\) [题目描述] 共 \(T\) 组测试点,每一组给出 \(2\) 个整数 \(n\) 和 \(k\),在 \( ...

  2. 题解 P4071 【[SDOI2016]排列计数】 (费马小定理求组合数 + 错排问题)

    luogu题目传送门! luogu博客通道! 这题要用到错排,先理解一下什么是错排: 问题:有一个数集A,里面有n个元素 a[i].求,如果将其打乱,有多少种方法使得所有第原来的i个数a[i]不在原来 ...

  3. hdu 5727 二分图+环排列

    Necklace Time Limit: 3000/1500 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Su ...

  4. BZOJ 一句话题解

    菜鸡刷题记录 [题号:题解] 1008:简单排列组合 #include <bits/stdc++.h> using namespace std; #define ll long long ...

  5. AtCoder Grand Contest 055题解

    我太菜啦!!!md,第一题就把我卡死了...感觉对构造题不会再爱了... A - ABC Identity 先来看这个题吧,题意就是给定你一个字符串,让你将这个字符串最多分成6个子串,使得每个字符都在 ...

  6. BZOJ1653: [Usaco2006 Feb]Backward Digit Sums

    1653: [Usaco2006 Feb]Backward Digit Sums Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 207  Solved:  ...

  7. ZOJ Monthly, March 2013

    A题 题目大意:给出一棵树,一开始节点值均为0,先要求完成在线操作:将某子树所有节点值取反,或者查询某子树总点权. 题解:很基础的线段树题,既然两个操作都是子树操作,那么就先树链剖分一下,将子树操作转 ...

  8. CODEFORCES 25E Test

    题意 三个字符串,找一个字符串(它的子串含有以上三个字符串)使它的长度最短,输出此字符串的长度. 题解 先枚举字符串排列,直接KMP两两匹配,拼接即可...答案取最小值.. 常数巨大的丑陋代码 # i ...

  9. Codeforces Round #209 (Div. 2)A贪心 B思路 C思路+快速幂

    A. Table time limit per test 1 second memory limit per test 256 megabytes input standard input outpu ...

随机推荐

  1. XSS靶场练习

    0x00:前言 一个XSS练习平台,闯关形式,一共20关 0x01:开始 第一行都是代码插入点,下面几行是payloads(插入点和payloads中间空一行) LV1 <script>a ...

  2. 个人项目-wc

    个人项目-WC   (C语言) 一.Github地址:https://github.com/Lin-J-F/WC 二.PSP表格 PSP2.1 Personal Software Process St ...

  3. Linux的基本指令(2)-Linux从入门到精通第三天(非原创)

    文章大纲 一.高级指令二.练习题三.学习资料下载四.参考文章   一.高级指令 1. hostname指令 作用:操作服务器的主机名(读取.设置)语法1:#hostname 含义:表示输出完整的主机名 ...

  4. docker gitlab-runner的安装

    参考: Run GitLab Runner in a container 前面介绍了gitlab-ce的安装,下面是gitlab-runner的安装,同样还是安装docker版本. 1.下载 dock ...

  5. 关于pytest的命令行传参

    #conftest.py import pytest def pytest_addoption(parser): #parser:用户命令行参数与ini文件值的解析器 # group = parser ...

  6. WPF系列 —— 控件添加依赖属性(转)

    WPF系列 —— 控件添加依赖属性 依赖属性的概念,用途 ,如何新建与使用.本文用做一个自定义TimePicker控件来演示WPF的依赖属性的简单应用. 先上TimePicker的一个效果图. 概念 ...

  7. C#使用Xamarin开发移动应用 ---- 系列文章

    C#使用Xamarin开发移动应用 C#使用Xamarin开发可移植移动应用终章(11.获取设备信息与常用组件,开源一个可开发模版.) C#使用Xamarin开发可移植移动应用进阶篇(10.综合演练, ...

  8. 201671010450-姚玉婷-实验十四 团队项目评审&课程学习总结

    项目 内容 所属科目 软件工程http://www.cnblogs.com/nwnu-daizh 作业要求 https://www.cnblogs.com/nwnu-daizh/p/11093584. ...

  9. ReSharper安装

    ReSharper是一个JetBrains公司出品的著名的代码生成工具,其能帮助Microsoft Visual Studio成为一个更佳的IDE.它包括一系列丰富的能大大增加C#和Visual Ba ...

  10. offsetHeight在不同的浏览器下取值不同

    今天在调js的时候,发现firefox和IE在取document.body.offsetHeight的值的时候结果不一样.上网查了一下,发现如下结果:   这四种浏览器分别为IE(Internet E ...