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); }
原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/12219373.html
时间: 2024-10-09 04:33:42