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

传送门:逆序排列 \([51nod1020]\)

【题目描述】

共 \(T\) 组测试点,每一组给出 \(2\) 个整数 \(n\) 和 \(k\),在 \([1,n]\) 共 \(n\) 个数字的全排列中,逆序数为 \(k\) 的排列种数,答案对 \(1e9+7\) 取模。

【样例】

样例输入:
1
4 3 样例输出:
6

【数据范围】

\(100\%\) \(1 \leqslant T \leqslant 10000,\) \(1 \leqslant N \leqslant 1000,\) \(1 \leqslant K \leqslant 20000\)

【分析】

用 \(dp[i][j]\) 表示 \([1,i]\) 的排列中逆序对数为 \(j\) 的排列种数,为方便枚举,用 \(ss[i]\) 表示长度为 \(i\) 的排列总数\((ss[i]=min\{K,\frac{i*(i-1)}{2}\}\)。

对于数字 \(i\) 来说,在一个 \([1,i-1]\) 的排列中它有 \(i\) 个位置可以加入,加下 \(i\) 之后新构成的逆序对数 \(k\in [0,i-1]\) 。

那么 \(dp\) 方程就出来了:\(dp[i][j]+=dp[i-1][j-k]\),其中 \(0 \leqslant j \leqslant ss[i],\) \(0 \leqslant j-k \leqslant ss[i-1]\) ,所以 \(max\{0,j-ss[i-1]\} \leqslant k \leqslant min\{j,i-1\}\) 。

即 \(dp[i][j]=\sum_{k=max\{0,j-ss[i-1]\}}^{min\{j,i-1\}}dp[i-1][j-k]\) 。

时间复杂度过高,要用前缀和优化一下,\(dp[i][j]=S[j-max(0,j-ss[i-1])]-S[j-min(i-1,j)-1]\),其中 \(S[i]=\sum_{j=0}^{i}dp[i-1][j]\) 。

但是前缀和下边界可能会取到 \(0\),减了 \(1\) 之后就成了 \(-1\),\(S[-1]\)是不存在的,所以每一次写 \(S[x]\) 都要改成 \(S[x+1]\)

还要先预处理答案,询问时直接 \(O(1)\) 查询。

时间复杂度为 \(O(NK)\) 。

【Code】

#include<algorithm>
#include<cstring>
#include<cstdio>
#define LL long long
#define Re register int
using namespace std;
const int N=1003,M=2e4+3,P=1e9+7;
int T,n,K,S[M],ss[N],dp[N][M];
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(){
n=1000,K=20000;
for(Re i=2;i<=n;++i){
ss[i]=i*(i-1)>>1;
if(ss[i]>K){for(Re j=i;j<=n;++j)ss[j]=K;break;}
}
for(Re i=1;i<=n;++i)dp[i][0]=1;
for(Re j=0;j<=ss[2];++j)(S[j+1]=S[j-1+1]+dp[1][j])%=P;
for(Re i=2;i<=n;++i){
for(Re j=1;j<=ss[i];++j)(dp[i][j]=(S[j-max(0,j-ss[i-1])+1]-S[j-min(i-1,j)-1+1]+P)%P)%=P;
for(Re j=0;j<=ss[i+1];++j)(S[j+1]=S[j-1+1]+dp[i][j])%=P;
}
in(T);while(T--)in(n),in(K),printf("%d\n",dp[n][K]);
}

【题解】逆序排列 [51nod1020]的更多相关文章

  1. 51nod 1020 逆序排列 DP

    在一个排列中,如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数,那么它们就称为一个逆序.一个排列中逆序的总数就称为这个排列的逆序数. 如2 4 3 1中,2 1,4 3,4 1,3 1是逆序 ...

  2. SQL-27 给出每个员工每年薪水涨幅超过5000的员工编号emp_no、薪水变更开始日期from_date以及薪水涨幅值salary_growth,并按照salary_growth逆序排列。 提示:在sqlite中获取datetime时间对应的年份函数为strftime('%Y', to_date)

    题目描述 给出每个员工每年薪水涨幅超过5000的员工编号emp_no.薪水变更开始日期from_date以及薪水涨幅值salary_growth,并按照salary_growth逆序排列. 提示:在s ...

  3. SQL-15 查找employees表所有emp_no为奇数,且last_name不为Mary的员工信息,并按照hire_date逆序排列

    题目描述 查找employees表所有emp_no为奇数,且last_name不为Mary的员工信息,并按照hire_date逆序排列CREATE TABLE `employees` (`emp_no ...

  4. Java数组逆序排列

    //逆序排列原理 /* A: 数组逆序原理* a: 题目分析* 通过观察发现,本题目要实现原数组元素倒序存放操作.即原数组存储元素为{12,69,852,25,89,588},逆序后为原数组存储元素变 ...

  5. 51nod 1020 逆序排列 递推DP

    1020 逆序排列  基准时间限制:2 秒 空间限制:131072 KB 分值: 80 难度:5级算法题  收藏  关注 在一个排列中,如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数,那么 ...

  6. C语言 · 逆序排列

    算法提高 逆序排列   时间限制:1.0s   内存限制:512.0MB      问题描述 编写一个程序,读入一组整数(不超过20个),并把它们保存在一个整型数组中.当用户输入0时,表示输入结束.然 ...

  7. 算法笔记_158:算法提高 逆序排列(Java)

    目录 1 问题描述 2 解决方案 1 问题描述 问题描述 编写一个程序,读入一组整数(不超过20个),并把它们保存在一个整型数组中.当用户输入0时,表示输入结束.然后程序将把这个数组中的值按逆序重新存 ...

  8. 51nod 1020 逆序排列——dp

    在一个排列中,如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数,那么它们就称为一个逆序.一个排列中逆序的总数就称为这个排列的逆序数. 如2 4 3 1中,2 1,4 3,4 1,3 1是逆序 ...

  9. 1020 逆序排列(DP)

    1020 逆序排列 基准时间限制:2 秒 空间限制:131072 KB 分值: 80 难度:5级算法题 在一个排列中,如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数,那么它们就称为一个逆序 ...

随机推荐

  1. linux部署docker镜像

    安装git yum install git 生成ssh秘钥 cat ~/.ssh/id_rsa.pub //查看是否有秘钥 ssh-keygen -t rsa -C "" //生成 ...

  2. sklearn---评价指标

    查看sklearn支持的评价指标: import sklearn sorted(sklearn.metrics.SCORERS.keys()) ['accuracy', 'adjusted_mutua ...

  3. php访问者模式(visitor design)

    终于搞定,累成一滩,今晚不想说话. <?php /* The visitor design pattern is a way of separating an algorithm from an ...

  4. POJ 3155Hard Life(最大密度子图)

    论文出处:最小割模型在信息学竞赛终的应用 #include <iostream> #include <cstdio> #include <cstring> #inc ...

  5. 嵌入式linux开发uboot启动过程源码分析(一)

    一.uboot启动流程简介 与大多数BootLoader一样,uboot的启动过程分为BL1和BL2两个阶段.BL1阶段通常是开发板的配置等设备初始化代码,需要依赖依赖于SoC体系结构,通常用汇编语言 ...

  6. 201871010121 王方 《面向对象程序设计(java)》 第二周学习总结

    这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 https://www.cnblogs.com/nwnu-daizh/p/11475 ...

  7. java JSONObject

    JSONObject.has("key")方法首先判断是否含有该key字段,如果不存在该字段,返回false;如果存在此字段,还判断了该字段的value值是否为null,如果val ...

  8. 关于时间排序在ios中失效的处理方法

    上个月公司做项目的时候在列表排序的时候产品加了一个需求,通过点击量,发布时间,评论量进行筛选的一个需求. 一开始在电脑上测试基本没问题,然后我也就放下了这个按耐不住的小心脏,然后在完成所有模块后 sh ...

  9. opengl第一个工程

    #include <iostream> #include <glad/glad.h> #include <GLFW/glfw3.h> void framebuffe ...

  10. win +R

    一.电脑设置免登录密码及修改密码 1.win+R 2.输入control userpasswords2 3.勾选免密码账号登陆,修改密码 二.打开性能监视器 1.win+R 2.输入perfmon.e ...