51nod-1020-reverse order

Baseline Time Limit: 2 seconds Space Limit: 131072 KB Score: 80  Difficulty: Level 5 Algorithm Questions
 collect
 focus on
In an arrangement, a pair of numbers is said to be in reverse order if they are in reverse order of magnitude, i.e. the preceding number is greater than the latter. The total number of inversions in a permutation is called the number of inversions of the permutation.
For example, in 2 4 3 1, 2 1, 4 3, 4 1, 3 1 are the reverse order, and the reverse order number is 4.

In the full permutation of 1-n, the minimum reverse order number is 0 (positive order), and the maximum is n*(n-1) / 2 (reverse order)
Given two numbers n and k, how many permutations are there with the inverse number k in the total permutations of 1-n?
For example: n = 4 k = 3.

In the arrangement of 1 2 3 4, there are 6 reverse order 3, which are:
1 4 3 2
2 3 4 1
2 4 1 3
3 1 4 2
3 2 1 4
4 1 2 3

Since the number of inversions is very large, just calculate and output the result of this number Mod 10^9 + 7.
Input
Line 1: A number T representing the number of numbers to use later as input tests. (1 <= T <= 10000)
Line 2 - T + 1: 2 numbers n, k per line. Separate them with spaces. (2 <= n <= 1000, 0 <= k <= 20000)
Output
A total of T rows, corresponding to the number Mod (10^9 + 7) in reverse order
Input example
1
4 3
Output example
6

题解:设dp[i][k]表示i个数有k个逆序数的数量,则dp[i - 1][x]可以理解成从第i位后(包括第i位)都按原有顺序排列,前i - 1个元素随机排列后产生x个逆序对的数量;当从dp[i - 1][]到dp[i][]时,按第i个元素所放位置可以产生(0 ~ i - 1)个逆序对,故dp[i][k] = dp[i - 1][k] + dp[i - 1][k -1] ... + dp[i -1][k - i + 1](注意k - 1 + 1要大于等于0)

根据上式可以继续推出dp[i][k] = dp[i][k - 1] + dp[i][k] - dp[i - 1][k - i](注意k - i 要大于等于0)

注意内存,long long开dp数组是放不下的,只能开int;

因为是要取模,所以注意取模前在括号内加上mod,防止变成负数。。。。

AC代码

#include <stdio.h>
#include <iostream>
#include <string>
#include <queue>
#include <map>
#include <vector>
#include <algorithm>
#include <string.h>
#include <cmath> 
typedef long long ll;
 
using namespace std;

const int maxn = 20001, mod = 1e9 + 7;
int dp[1002][maxn] = {0};

void get_ans(){
	for(int i = 1; i <= 1001; i++){
		dp[i][0] = 1;
		int len;
		if(i <= 200)
			len = (i - 1) * i / 2;
		else
			len = 20000;
		for(int k = 1; k <= len; k++){
			dp[i][k] = (int)(((ll)dp[i][k - 1] + (ll)dp[i - 1][k] - (ll)(k - i >= 0 ? dp[i - 1][k - i] : 0) + (ll)mod) % (ll)mod);
		}
	}
}

int main(){
	int n, k, t;
	get_ans();
	scanf("%d", &t);
	while(t--){
		scanf("%d %d", &n, &k);
		printf("%d\n", dp[n][k]);	
	}
	return 0;
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325986384&siteId=291194637