前缀和、滚动数组优化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 } 
View Code

 

posted on 2016-11-15 08:12  Absolutezero  阅读(552)  评论(0编辑  收藏  举报