T1:
求由 1 到 n 一共 n 个数字组成的所有排列中,逆序对个数为 k 的有多少个。
对每组数据输出答案对 10000 取模后的结果。
输入
1
4 1
输出
3对于所有数据,满足:n≤1000, k≤1000,T≤10
首先可以想到O(n^3)的动规;
f[i][j]表示 1,2,3...,i组成的逆序对为j个的数量,可以过30%的数据。
注意到k≤1000,可以用下标和来求,
g[i][j]=f[i][0]+f[i][1]+f[i][2].....+f[i][j]
g[i][j]=g[i][j-1]+f[i][j]
if(i>j) f[i][j]=g[i-1][j]
if(i<=j) f[i][j]=g[i-1][j]-g[i-1][j-i] //f[i-1][0],f[i-1][1]...f[i-1][j-i] 对f[i][j]没有影响,因为加入i后最多增加i-1个逆序对
#include<bits/stdc++.h>
using namespace std;
int t,n,k;
int a[1008][1008];
inline void work(){
memset(a,0,sizeof(a));
for(int i=0;i<=n;++i) a[i][0]=1;
for(int i=1;i<=k;++i) a[0][i]=1;
for(int i=1;i<=n;++i)
for(int j=1;j<=k;++j){
a[i][j]=a[i][j-1]+a[i-1][j];
if(j>=i) a[i][j]=a[i][j]-a[i-1][j-i];
a[i][j]%=10000;
}
cout<<(a[n][k]-a[n][k-1]+10000)%10000<<endl;
return ;
}
int main(){
// freopen("permut.in","r",stdin);
// freopen("permut.out","w",stdout);
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&k);
work();
}
return 0;
}