Fabricating Sculptures dp+前缀和优化

题目链接: https://codeforces.com/gym/102428/problem/F

题意:

你现在有 m m m 个方块,要搭建一个以 s s s 为底的一个模型,这个模型是不能储水的结构,即不存在一列,其左边和右边的俩均比它高,问你有多少种搭建的方法。

做法:

d p [ i ] [ j ] dp[i][j] dp[i][j] 表示以 i i i 为底的时候,还有 j j j 个方块时的方案数。这个时候 d p [ i ] [ j ] = 1 ∗ d p [ i ] [ j − i ] + 2 ∗ d p [ i − 1 ] [ j − i + 1 ] + 3 ∗ d p [ i − 2 ] [ j − i + 2 ] . . . dp[i][j]=1*dp[i][j-i]+2*dp[i-1][j-i+1]+3*dp[i-2][j-i+2]... dp[i][j]=1dp[i][ji]+2dp[i1][ji+1]+3dp[i2][ji+2]... ,这个式子很容易得出,但是在原来我们做的时候,用记忆化搜索对于每一个 d p [ i ] [ j ] dp[i][j] dp[i][j] f o r for for 了一次所有的情况,所以就 T T T 了,这个结构我们可以发现是 可以用两个前缀和来维护的,一个维护 s u m [ i + j ] sum[i+j] sum[i+j] 的前缀和,另一个维护上面那样,所谓前缀和的前缀和。

代码

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;

typedef long long ll;
const int maxn=5005;
const int mod=(int)1e9+7;
int n,m;
ll sum[maxn*2],psum[maxn*2],dp[maxn][maxn];
int main() {
    scanf("%d%d",&n,&m);
    m-=n;
    for(int s=1;s<=n;s++){
        for(int res=0;res<=m;res++){
            psum[res]=(psum[res]+sum[res])%mod;
            if(res==0) dp[s][res]=1;
            else  dp[s][res]=(dp[s][res]+psum[res])%mod;
            sum[s+res]=(sum[s+res]+dp[s][res])%mod;
        }
    }
    printf("%lld\n",dp[n][m]);
	return 0;
}
©️2020 CSDN 皮肤主题: 技术黑板 设计师:CSDN官方博客 返回首页