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],如何用容斥即可。
#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;
}