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; }