Problem F – Fabricating Sculptures

Problem F – Fabricating Sculptures

https://codeforces.com/gym/102428/problem/F

这是一个按层决策的dp,即它只能有一个极值而且是最大值,我当时是想的按列处理,结果卡住了
但是如果按行从下往上来看,它就是单调不增的
f[i][j]表示已经放置了i个箱子且最上面一行为j个箱子的方案数
f[i][j]=sigema(j<=k<=S)f[i-j][k]*(k-j+1)

f[i][j]=f[i-j][j]*1+f[i-j][j+1]*2+...+f[i-j][S]*(S-j+1);

维护两个前缀和
sum0[i][j]表示f[i][1]*1+...+f[i][j]*j
sum1[i][j]表示f[i][1]+...+f[i][j]
所以f[i][j]=sum0[i-j][S]-sum0[i-1][j-1]-(j-1)*(sum1[i-j][S]-sum1[i-1][j-1])

#include <bits/stdc++.h>
#define inf 2333333333333333
#define N 5010
#define p(a) putchar(a)
#define For(i,a,b) for(long long i=a;i<=b;++i)
//by war
//2020.10.13
using namespace std;
long long S,B,ans,mod=1e9+7;
long long f[N][N],sum0[N][N],sum1[N][N];
void in(long long &x){
    long long y=1;char c=getchar();x=0;
    while(c<'0'||c>'9'){if(c=='-')y=-1;c=getchar();}
    while(c<='9'&&c>='0'){ x=(x<<1)+(x<<3)+c-'0';c=getchar();}
    x*=y;
}
void o(long long x){
    if(x<0){p('-');x=-x;}
    if(x>9)o(x/10);
    p(x%10+'0');
}

signed main(){
    in(S);in(B);
    f[S][S]=1;sum0[S][S]=S;sum1[S][S]=1;
    For(i,S+1,B){
        For(j,0,S){
            f[i][j]=sum0[i-j][S]-sum0[i-j][j-1]-(j-1)*(sum1[i-j][S]-sum1[i-j][j-1]);
            f[i][j]%=mod;
        }
        For(j,0,S){
            sum0[i][j]=(sum0[i][j-1]+j*f[i][j]%mod)%mod;
            sum1[i][j]=(sum1[i][j-1]+f[i][j])%mod;
        }
    }
    For(j,0,S) ans=(ans+f[B][j])%mod;
    o((ans+mod)%mod);
    return 0;
}
原文地址:https://www.cnblogs.com/war1111/p/13810175.html