前缀和、滚动数组优化dp
f[i][j]表示前i个数,逆序对数为j的方案数
我们知道,在第k个位置放第i个数,单步得到的逆序对数为i-k
则在前i个数,最多能产生的逆序对数为i个,最少0个,均可转移到j
所以我们得到:f[i][j]=sum(f[i-1][j...j-i])
所以我们可以通过前缀和优化j
滚动数组消去 i 的一维
这样时间复杂度由n^2k变为nk,空间由nk变为k
1 #include<cstdio> 2 #include<cstring> 3 using namespace std; 4 const int N=1010,p=10000; 5 int n,k,f[N],sum[N]; 6 int main(){ 7 scanf("%d %d",&n,&k); 8 f[0]=1; 9 for (int i=1;i<=n;i++){ 10 sum[0]=f[0]; 11 for (int j=1;j<=k;j++) 12 sum[j]=(sum[j-1]+f[j])%p; 13 for (int j=k;j>=1;j--){ 14 f[j]=(f[j]+sum[j-1])%p; 15 if (j>=i) 16 f[j]=(f[j]-sum[j-i]+p)%p; 17 } 18 } 19 printf("%d",f[k]%p); 20 return 0; 21 }