51nod 1020 逆序排列

51nod 1020 逆序排列

学习笔记

其实要预处理,但唐的我非要每次都求一遍。

设状态为 \(dp[i][j]\) 选了 i 个数逆序对数为 j 的排序种类数。

首先初始化 \(dp[i][0]=1\) 即没有逆序对,转移方程 \(dp[i][j]=dp[i-1][j]+dp[i-1][j-1]+……+dp[i-1][j-i]\) 这是显然的(放上这个数,会产生的逆序对数)可以用前缀和优化,但可以发现 dp 数组本身就是前缀和 dp[i][j-1],如何用容斥即可。

image

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define min(a,b) (a<b)?a:b
const int mod=1e9+7;
int n,t,m,k;
ll x;
int dp[1002][20002];

int main(){
    ios::sync_with_stdio(false);
    cin>>t;
    for(int i=2;i<=1000;i++){
		dp[i][0]=1;
    	for(int j=1;j<=i*(i-1)/2&&j<=20000;j++){
    		x=(j>=i)?dp[i-1][j-i]:0;
    		dp[i][j]=(dp[i][j-1]+dp[i-1][j]-x+mod)%mod;	
		}
	}
    while(t--){
    	cin>>n>>k;
		cout<<dp[n][k]<<"\n";
	}
    return 0;
}

posted @ 2024-09-09 16:00  sad_lin  阅读(3)  评论(0编辑  收藏  举报