定义dp[i][j]为1~i的排列里逆序数为j的方案数。那么只需要求i阶段的dp值时,只需要考虑在i-1阶段的基础上把i放哪里就好了,如果i放在倒数第v个就会新产生v-1个逆序对。那么转移方程就是dp[i][j]=sum(dp[i-1][j-v]) 0<=v<=min (j,i-1),如果单单这样的话复杂度是n*k*k,因为转移是由上一阶段一个连续区间的dp值转移来的,所以在算i阶段dp值时可以先处理出i-1阶段dp值的前缀和,这样转移就O(1)了
#include<bits/stdc++.h>
using namespace std;
#define ls rt<<1
#define rs (rt<<1)+1
#define PI acos(-1)
#define eps 1e-8
#define ll long long
#define fuck(x) cout<<#x<<" "<<x<<endl;
typedef pair<int,int> pii;
const int inf=2e9;
const int maxn=1e6+10;
const int mod=1e9+7;
int d[4][2]={1,0,-1,0,0,1,0,-1};
//int lowbit(int x){return x&-x;}
//void add(int x,int v){while(x<=n)bit[x]+=v,x+=lowbit(x);}
//int sum(int x){int ans=0;while(x>=1) ans+=bit[x],x-=lowbit(x);return ans;}
inline ll read() {
ll s = 0,w = 1;
char ch = getchar();
while(!isdigit(ch)) {
if(ch == '-') w = -1;
ch = getchar();
}
while(isdigit(ch))
s = s * 10 + ch - '0',ch = getchar();
return s * w;
}
inline void write(ll x) {
if(x < 0)
putchar('-'), x = -x;
if(x > 9)
write(x / 10);
putchar(x % 10 + '0');
}
int dp[1005][(int)2e4+10],pre[(int)2e4+10];
int main(){
dp[1][1]=0,dp[1][0]=1;
pre[0]=1,pre[1]=1;
for(int i=2;i<=1000;i++){
for(int j=0;j<=min(20000,i*(i-1)/2);j++) {
if (i - 1 >= j)
dp[i][j] = pre[j];
else
dp[i][j] = (pre[j] - pre[j - i]+mod)%mod;
}
for(int j=0;j<=20000;j++){
if(j==0)
pre[j]=dp[i][j];
else
pre[j]=(pre[j-1]+dp[i][j])%mod;
}
}
int t,n,k;
t=read();
while(t--){
n=read();k=read();
write(dp[n][k]);puts("");
}
return 0;
}