51nod 1020:逆序排列 DP
2016-02-11 13:27
295 查看
1020 逆序排列
基准时间限制:2 秒 空间限制:131072 KB 分值: 80 难度:5级算法题
收藏
关注
在一个排列中,如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数,那么它们就称为一个逆序。一个排列中逆序的总数就称为这个排列的逆序数。
如2 4 3 1中,2 1,4 3,4 1,3 1是逆序,逆序数是4。
1-n的全排列中,逆序数最小为0(正序),最大为n*(n-1) / 2(倒序)
给出2个数n和k,求1-n的全排列中,逆序数为k的排列有多少种?
例如:n = 4 k = 3。
1 2 3 4的排列中逆序为3的共有6个,分别是:
1 4 3 2
2 3 4 1
2 4 1 3
3 1 4 2
3 2 1 4
4 1 2 3
由于逆序排列的数量非常大,因此只需计算并输出该数 Mod 10^9 + 7的结果就可以了。
Input
Output
Input示例
Output示例
dp
[k]表示n个数,逆序数为k的个数。考虑从n-1个数里面递推,就是将n放到哪一个位置,放到第i个位置就会增加n-i个逆序数。所以可知,有dp
[k]=sum(dp[n-1][k-i])(0<=i<n)。对每一步求前缀和。
后来发现其实不用滚动数组也是可以的,dp[1005][20005]是可以开出来的。
代码:
基准时间限制:2 秒 空间限制:131072 KB 分值: 80 难度:5级算法题
收藏
关注
在一个排列中,如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数,那么它们就称为一个逆序。一个排列中逆序的总数就称为这个排列的逆序数。
如2 4 3 1中,2 1,4 3,4 1,3 1是逆序,逆序数是4。
1-n的全排列中,逆序数最小为0(正序),最大为n*(n-1) / 2(倒序)
给出2个数n和k,求1-n的全排列中,逆序数为k的排列有多少种?
例如:n = 4 k = 3。
1 2 3 4的排列中逆序为3的共有6个,分别是:
1 4 3 2
2 3 4 1
2 4 1 3
3 1 4 2
3 2 1 4
4 1 2 3
由于逆序排列的数量非常大,因此只需计算并输出该数 Mod 10^9 + 7的结果就可以了。
Input
第1行:一个数T,表示后面用作输入测试的数的数量。(1 <= T <= 10000) 第2 - T + 1行:每行2个数n,k。中间用空格分隔。(2 <= n <= 1000, 0 <= k <= 20000)
Output
共T行,对应逆序排列的数量 Mod (10^9 + 7)
Input示例
1 4 3
Output示例
6
dp
[k]表示n个数,逆序数为k的个数。考虑从n-1个数里面递推,就是将n放到哪一个位置,放到第i个位置就会增加n-i个逆序数。所以可知,有dp
[k]=sum(dp[n-1][k-i])(0<=i<n)。对每一步求前缀和。
后来发现其实不用滚动数组也是可以的,dp[1005][20005]是可以开出来的。
代码:
#pragma warning(disable:4996) #include <iostream> #include <algorithm> #include <cstring> #include <vector> #include <string> #include <cstdio> #include <cmath> #include <queue> #include <stack> #include <deque> #include <set> #include <map> using namespace std; #define INF 0x3fffffff typedef long long ll; const int mod = 1e9 + 7; const int maxn = 20005; int ans[maxn], dp[3][maxn]; struct no { int n, k; int id; }node[maxn]; bool cmp(no n1, no n2) { if (n1.n == n2.n) { return n1.k < n2.k; } else { return n1.n < n2.n; } } void solve() { int mn, mk; int i, j, k, t; scanf("%d", &t); mn = 0; mk = 0; for (i = 1; i <= t; i++) { scanf("%d%d", &node[i].n, &node[i].k); node[i].id = i; mn = max(mn, node[i].n); mk = max(mk, node[i].k); } memset(ans, 0, sizeof(ans)); sort(node + 1, node + t + 1, cmp); int st, pre_sum, pre = 0, now = 1, p = 1; dp[0][0] = 1; for (i = 2; i <= mn; i++) { k = min(i*(i - 1) / 2, mk); for (j = 0; j <= k; j++) { st = max(0, j - i + 1); pre_sum = st == 0 ? 0 : dp[pre][st - 1]; dp[now][j] = (dp[pre][j] - pre_sum + mod) % mod; if (j >= 1)dp[now][j] = (dp[now][j] + dp[now][j - 1]) % mod; } while (p <= t) { if (node[p].n != i) break; ans[node[p].id] = dp[now][node[p].k]; p++; } now ^= 1; pre ^= 1; } for (i = 1; i <= t; i++) printf("%d\n", ans[i]); } int main() { //freopen("i.txt","r",stdin); //freopen("o.txt","w",stdout); solve(); //system("pause"); return 0; }
相关文章推荐
- HashTable和HashMap的区别
- bzoj3110 K大数查询
- ecliplse 远程提交程序到虚拟机 hadoop集群 , 修改Hadoop的源代码---NativeIO问题解决!
- Java的多线程之基础篇
- Ubuntu终端常用的快捷键
- vxWorks测量一个函数的执行时间(timexLib)
- 2015读过的书与看过的影视资料
- secuteCRT的使用
- 文章标题
- Java中 ArrayList、Vector和LinkedList
- latex初探
- Android学习笔记二
- BZOJ 4264: 小C找朋友|Hash
- android 文件上传
- hdu 1512 Monkey King
- [BZOJ4300] 绝世好题
- poj 3984迷宫问题(bfs加打印路径)
- 最新 Sublime Text3 激活码 (Build 3103 有效)
- 生产环境 JDK6 升级 JDK8
- pyhon3.4 requests模块模拟post登陆csdn