Educational Codeforces Round 80 C. Two Arrays

http://codeforces.com/contest/1288/problem/C

 

题意:

用1—n构造两个长为m的数组a,b

满足a[i]<=b[i],a单调不减,b单调不增

求方案数

 

令dp[i][j][k] 表示构造了长度为i,a[i]=j,b[i]=k的方案数

dp[i][j][k]=Σ dp[i-1][h][p] (h<=p,h<=i,p>=k)

时间复杂度:m*n^4

前缀和、后缀和 优化:

sum[i][j][k] 表示 Σ dp[i][1—j][k—n]

求的时候可以先用后缀和算 sum[i][j][k]=Σ dp[i][j][k—n]

再用前缀和算 sum[i][j][k]=Σ sum[i][1—j][k]

 

 

#include<cstdio>
 
using namespace std;
 
const int mod=1e9+7;
 
int dp[11][1001][1001],sum[11][1001][1001];
 
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;++i)
    {
        for(int j=i;j<=n;++j) 
        {
            dp[1][i][j]=1;
            sum[1][i][j]=1;
        }
        for(int j=n-1;j>=i;--j) sum[1][i][j]+=sum[1][i][j+1];
    }
    for(int j=1;j<=n;++j)
        for(int k=2;k<=j;++k)
            sum[1][k][j]+=sum[1][k-1][j];
    for(int i=2;i<=m;++i)
    {
        for(int j=1;j<=n;++j)
        {
            for(int k=j;k<=n;++k)
            {
                dp[i][j][k]=sum[i-1][j][k];
                sum[i][j][k]=dp[i][j][k];
            }
            for(int k=n-1;k>=j;--k) sum[i][j][k]=(sum[i][j][k]+sum[i][j][k+1])%mod;
        }
        for(int k=1;k<=n;++k)
            for(int j=2;j<=k;++j)
                sum[i][j][k]=(sum[i][j][k]+sum[i][j-1][k])%mod;
    }
    int ans=0;
    for(int i=1;i<=n;++i)
        for(int j=i;j<=n;++j)
            ans=(ans+dp[m][i][j])%mod;
    printf("%d",ans);
}
posted @ 2020-01-20 20:47  TRTTG  阅读(220)  评论(0编辑  收藏  举报