思路:离线dp,dp[n][k]表示n个数k个逆序数的数量,状态转换方程有点思路。
对于dp[n][k],最大的一个数n的位置放置在第n-i(0<=i<=n-1)位置上时,n所产生的逆序数为n-(n-i)=i,因此
dp[n][k]=sum{dp[n-1][k-i]} (0<=i<=n-1)
同理,dp[n][k-1]=sum{dp[n-1][k-1-i}(0<=i<=n-1)
则dp[n][k]-dp[n][k-1]=(dp[n-1][k]+dp[n-1][k-1]+...+dp[n-1][k-n+1])-(dp[n-1][k-1]+dp[n-1][k-2]+...+dp[n-1][k-n+1]+dp[n-1][k-n])
=dp[n-1][k]-dp[n-1][k-n]
转换下,dp[n][k]=dp[n][k-1]+dp[n-1][k]-dp[n-1][k-n];
Code :
#include<iostream>
using namespace std;
const int MOD=1e9+7;
const int MAX_N=1005;
const int MAX_M=20005;
int n,m,T;
int dp[MAX_N][MAX_M];
int main()
{
ios::sync_with_stdio(false);
for(int i=1;i<MAX_N;++i)
dp[i][0]=1;
for(int i=1;i<MAX_N;++i)
for(int j=1,t=i*(i-1)/2;j<MAX_M&&j<=t;++j)
{
dp[i][j]=(dp[i][j-1]+dp[i-1][j])%MOD;
if(j>=i) dp[i][j]=(dp[i][j]+MOD-dp[i-1][j-i])%MOD;
}
cin>>T;
while(T--){
cin>>n>>m;
cout<<dp[n][m]<<endl;
}
return 0;
}