dp - 逆序数序列
对于一个数列{ai},如果有i<j且ai>aj,那么我们称ai与aj为一对逆序对数。若对于任意一个由1~n自然数组成的
数列,可以很容易求出有多少个逆序对数。那么逆序对数为k的这样自然数数列到底有多少个?
Input
第一行为两个整数n,k。
Output写入一个整数,表示符合条件的数列个数,由于这个数可能很大,你只需输出该数对10000求余数后的结果。
Sample Input4 1
Sample Output
3
样例说明: 下列3个数列逆序对数都为1;分别是1 2 4 3 ;1 3 2 4 ;2 1 3 4; 100%的数据 n<=1000,k<=1000
题意:让你求长度为 N 的序列逆序数为K的有多少种情况
思路分析:考虑在增加一位,第 i 位时,就相当于在长度为i-1的序列全排列中插入以个 i ,由于插入的 i 值是最大的,因此其可以增加的逆序数数量为 0~i-1 ,当将 i 插入到最末尾时,不会增加任何逆序数,当插入到倒数第二位时,会增加一位逆序数,就这样推一下就可以了。
定义 dp[i][j] 长度为 i 的序列逆序数为 j 的方案总数,在累加求和时要用前缀和优化一下
代码示例:
int dp[1005][1005]; int sum[1005]; int main() { //freopen("in.txt", "r", stdin); //freopen("out.txt", "w", stdout); int n, k; cin >> n >> k; dp[0][0] = 0; for(int i = 1; i <= n; i++){ dp[i][0] = 1; for(int j = 1; j <= k; j++){ int s = max(0, j-i+1); int e = j; if (s == 0) dp[i][j] = sum[e]; else dp[i][j] = (sum[e]+mod-sum[s-1])%mod; } sum[0] = 1; for(int j = 1; j <= k; j++) { sum[j] = sum[j-1]+dp[i][j]; sum[j] %= mod; } } printf("%d\n", dp[n][k]); return 0; }
东北日出西边雨 道是无情却有情