【ZROI】【DP】【17 提高 3】建造

本文介绍了一种通过动态规划计算特定建造顺序下方案数量的方法。该方法关注于满足一定条件的数组构造,即每个元素大于等于相邻建筑的高度,并且总和不超过给定限制。文章详细解释了动态规划的状态定义与转移过程,最终给出了一个时间复杂度为O(n^4)的解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

假设我们已经确定了一个建造的顺序,那么如何计算按照这个顺序建造的方案数?这就相当于确定一个数组d,其中di<=X∑di<=X并且di>=max{hi,hi+1}di>=max{hi,hi+1},为了方便起见,记max{hi,hi+1}=S∑max{hi,hi+1}=S,d数组的个数显然就是CnX1S+nCX−1−S+nn(把X-1-S个苹果分给n+1个人,因为是小于等于X,所以要多一个人出来),现在,我们就只关心每一个S所对应的建造顺序的个数了。

可以用DP。可以利用建筑高度为1~n的排列的性质,从小到大的DP,这样,每次加入的max都是当前的高度。定义fi,j,kfi,j,k​表示高度为1~i,S=j,还有k个位置需要插入建筑的方案数,fn,j,0fn,j,0​就是S=j时的方案数。考虑如何转移,显然每次插入可以有三种情况,一种是两边都需要再插入,一种是只有一边需要再插入,还有一种是两边都不需要再插入,分类讨论一下。需要注意的是,这里之所以还要定义第三维,就是因为如果不能确定是否还需要再插入建筑的话,S的值就无法更新。最后还要注意一下插入两边端点的情况。

时间复杂度:O(n4)O(n4)

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxm 100106
#define maxn 106
#define LL long long
using namespace std;
int n,X,P;
LL ans,inv[maxm],fact[maxm],f[2][maxn*maxn][maxn];
LL C(int x,int y){return fact[x]*inv[y]%P*inv[x-y]%P;}
int main(){
    freopen("3.in","r",stdin);
    freopen("3.out","w",stdout);
    scanf("%d%d%d",&n,&X,&P);
    inv[1]=1;
    for(int i=2;i<=100100;i++)inv[i]=(LL)(P-P/i)%P*inv[P%i]%P;
    for(int i=2;i<=100100;i++)(inv[i]*=inv[i-1])%=P;
    fact[1]=1;
    for(int i=2;i<=100100;i++)fact[i]=fact[i-1]*i%P;
    f[1][0][0]=1;
    for(int i=1;i<n;i++){
     memset(f[(i&1)^1],0,sizeof(f[(i&1)^1]));
     for(int j=0;j<=i*i;j++)
      for(int k=0;k<i;k++) if(f[i&1][j][k]){
        (f[(i&1)^1][j+2*(i+1)][k-1]+=f[i&1][j][k]*k%P)%=P;
        (f[(i&1)^1][j][k+1]+=f[i&1][j][k]*k%P)%=P;
        (f[(i&1)^1][j+i+1][k]+=f[i&1][j][k]*k%P*2%P)%=P;
        (f[(i&1)^1][j+i+1][k]+=f[i&1][j][k]*2%P)%=P;
        (f[(i&1)^1][j][k+1]+=f[i&1][j][k]*2%P)%=P;
      }
    }
    for(int j=0;j<=n*n;j++)if(f[n&1][j][0])(ans+=C(X-j-1+n,n)*f[n&1][j][0]%P)%=P;
    printf("%lld\n",ans);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值