题意:
逆序对指在一个序列中ai>aj && i < j,也就是一前一后两个数,当大的在前面的时候即算一对。

题目求在一个由1…n组成的序列中逆序对为k的序列的个数。
出题人很良心,不需要写高精度,答案对10000取模即可。

思路:
这道题的前面其实还有一道很类似的题,也是求逆序对。不同的是那道题给定了序列求逆序对的个数,而这道题则相反。那道题的方法即merge sort。尽管两题很类似,但是方法却截然不同。

凭感觉,这应该是一道动规的题。长度为n-1的序列与长度为n的序列只差一个n,而由于n出现的逆序对也很好求:n在第i个就会相比于原序列多出n-i个逆序对。如此,那看来是动规无疑了。

状态转移方程:若长度为n的序列要求有k个逆序对,那么他可以从长为n-1的序列中选取有k-n+1到k个逆序对的部分。道理很简单n的加入最多使原序列增加n-1个逆序对(即放在第一个的时候,与后面n-1个数构成逆序对),所以要从x[n-I][p]变到x[n][k],p属于[k-n+1,k]。那么转移方程式就很好写了:

for(unsigned i = 2; i != n+1; ++i)
{
dp[i][0] = 1;
for(unsigned j = 1; j != k+1; ++j)
{
for(unsigned p = k-j+1; p != j+1; ++p)
{
dp[i][j] += dp[i-1][p];
}
}
}

优化:
这是一个O(n^3)的算法,很慢。我们观察最内层循环,发现它很多余,因为总是重复操作。dp[i][j-1]和dp[i][j]当i-j+1>0的时候,中间部分完全相同,只是掐头增尾的问题。由此我们可以有第一种优化:dp[i][j] = dp[i][j-1]-dp[i-1][j-i]+dp[i-1][j];(j-i >-1)

当然也可以直接采用前缀数组和的方式将这段循环优化掉,到O(n^2)。
(后面的代码采取的是这一种)

源代码的读入是多组数据。


源代码:

#include <bits/stdc++.h>
#define maxn 1005
#define mod 10000
//#define DEBUG
#ifdef DEBUG
#define debug(...)printf(__VA_ARGS__);
#else
#define debug(...)
#endif
using namespace std; int n[15], k[15], dp[maxn][maxn*10]; void Dp(int n, int k)
{
int a;
memset(dp, 0, sizeof dp);
for(unsigned i = 0; i != k+1; ++i)
{
dp[1][i] = 1;
}
for(int i = 2; i != n+1; ++i)
{
dp[i][0] = 1;
for(int j = 1; j != k+1; ++j)
{
if(j-i > -1) a = dp[i-1][j-i];
else a = 0;
dp[i][j] = (dp[i][j-1]+dp[i-1][j]-a+mod)%mod;
debug("%d ", dp[i][j]);
}
debug("\n");
}
return ;
} int main()
{
//freopen("test.in", "r", stdin);
int times, Maxn = 0, Maxk = 0;
scanf("%d", &times);
for(unsigned i = 0; i != times; ++i)
{
scanf("%d%d", &n[i], &k[i]);
Maxn = max(Maxn, n[i]);
Maxk = max(Maxk, k[i]);
}
Dp(Maxn, Maxk);
for(unsigned i = 0; i != times; ++i)
{
printf("%d\n", (mod+dp[n[i][k[i]]-dp[n[i]][k[i]-1])%mod);
}
return 0;
}

箜瑟_qi 2017.04.27 15:01

luogu 1521-求逆序对的更多相关文章

  1. 2021.12.10 P5041 [HAOI2009]求回文串(树状数组求逆序对)

    2021.12.10 P5041 [HAOI2009]求回文串(树状数组求逆序对) https://www.luogu.com.cn/problem/P5041 题意: 给一个字符串 \(S\) ,每 ...

  2. HDU 3743 Frosh Week(归并排序求逆序对)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3743 题目意思就是给你一个长为n的序列,让你求逆序对.我用的是归并排序来求的.归并排序有一个合并的过程 ...

  3. AC日记——codevs 1688 求逆序对

    1688 求逆序对  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 黄金 Gold 题解  查看运行结果     题目描述 Description 给定一个序列a1,a2,…, ...

  4. POJ2299Ultra-QuickSort(归并排序 + 树状数组求逆序对)

    树状数组求逆序对   转载http://www.cnblogs.com/shenshuyang/archive/2012/07/14/2591859.html 转载: 树状数组,具体的说是 离散化+树 ...

  5. codevs1688 求逆序对

    题目描述 Description 给定一个序列a1,a2,…,an,如果存在i<j并且ai>aj,那么我们称之为逆序对,求逆序对的数目 数据范围:N<=105.Ai<=105. ...

  6. HDU 4911 http://acm.hdu.edu.cn/showproblem.php?pid=4911(线段树求逆序对)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4911 解题报告: 给出一个长度为n的序列,然后给出一个k,要你求最多做k次相邻的数字交换后,逆序数最少 ...

  7. SGU 180 Inversions(离散化 + 线段树求逆序对)

    题目链接:http://acm.sgu.ru/problem.php?contest=0&problem=180 解题报告:一个裸的求逆序对的题,离散化+线段树,也可以用离散化+树状数组.因为 ...

  8. 树状数组求逆序对:POJ 2299、3067

    前几天开始看树状数组了,然后开始找题来刷. 首先是 POJ 2299 Ultra-QuickSort: http://poj.org/problem?id=2299 这题是指给你一个无序序列,只能交换 ...

  9. wikioi 1688 求逆序对

    /*=========================================================== wikioi 1688 求逆序对 时间限制: 1 s 空间限制: 12800 ...

  10. 【剑指offer】求逆序对的个数

    2013-09-07 10:50:31 面试题36:在数组中的两个数字如果前面一个数字大于后面的数字,则这两个数字构成一个逆序对.输入一个数组,求出这个数组中逆序对的总数. 小结: 最直观的的方法是: ...

随机推荐

  1. 解决MVC中JsonResult返回 弹出文件下载对话框

    设置一下返回类型为HTML TEXT就可以了 JsonResult json = Json(xxx, JsonRequestBehavior.DenyGet); json.ContentType = ...

  2. JavaScript入门必备

    1.JavaScript和Java没有关系,JavaScript是一门(客服端)脚本语言,并且是一个解释性语言. 2.添加JavaScript的方法 (1)内联:通过<script>js代 ...

  3. [项目记录] 用c语言完成的一个学生成绩管理系统

    一.要求: 学生成绩管理系统 某班有最多不超过30人(具体人数由键盘输入)参加期末考试,最多不超过6门(具体门数由键盘输入).使用链表编程实现如下菜单驱动的学生成绩管理系统. 从文件读入每个学生个人信 ...

  4. 使用moment.js轻松管理日期和时间

    大家在前端Javascript开发中会遇到处理日期时间的问题,经常会拿来一大堆处理函数才能完成一个简单的日期时间显示效果.今天我给大家介绍一个轻量级的Javascript日期处理类库:moment.j ...

  5. ubuntu-terminal快捷键

    常用快捷键功能:Tab 自动补全 Ctrl+a 光标移动到开始位置 Ctrl+e 光标移动到最末尾 Ctrl+k 删除此处至末尾的所有内容 Ctrl+u 删除此处至开始的所有内容 Ctrl+d 删除当 ...

  6. linux 下的 mkfifo、exec 命令使用

    MKFIFOSection: User Commands (1)Updated: 1998年11月Index Return to Main Contents  NAME(名称)mkfifo - 创建F ...

  7. State模式学习笔记

    选用了一个假设需要用户验证的例子进行State模式学习,这个例子并不恰当.无所谓了,只要能学习到其中的内容即可. 适用性: 1,一个对象的行为取决于他的状态,并且它必须在运行时刻依据状态改变他的行为. ...

  8. Hibernate基础学习(一)—初识Hibernate

    一.对象的持久化 狭义的理解: 持久化仅仅指把对象永久的保存到数据库中. 广义的理解: 持久化包括和数据库相关的各种操作.         保存: 把对象永久保存到数据库中.         更新: ...

  9. Linux Smaba服务器配置

    Linux系统默认已经安装了Samba,但是没有安装Samba服务: 1,先查看安装情况:rpm -qa|grep samba 根据系统的安装情况选择下载或者通过光驱安装所缺的rpm包. 我的安装情况 ...

  10. 基于Flink的windows--简介

    新的一年,新的开始,新的习惯,现在开始. 1.简介 Flink是德国一家公司名为dataArtisans的产品,2016年正式被apache提升为顶级项目(地位同spark.storm等开源架构).并 ...