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;
}