JZOJ 5192. 【NOI2017模拟7.2】容器

Description

Description

Input

Input

Output

Output

Sample Input

样例一:3 2 1
样例二:15 6 4

Sample Output

样例一:10
样例二:458177764

Data Constraint

Data Constraint

Hint

样例一解释:
Hint

Solution

  • 对于这种求方案数的问题,我们考虑DP。

  • 我们考虑逐个位置填区间,比如说做到了第 i i 个容器。

  • 那么在填了的区间(设共有 j 个)中,肯定有些已经闭合了,有些尚未闭合(设为 k k 个)。

  • 那么我们就得到了状态 f[i][j][k] 表示此时的方案数,显然 f[0][0][0]=1 f [ 0 ] [ 0 ] [ 0 ] = 1

  • 如何转移呢?我们想想这时我们可以做什么,闭合某些尚未闭合的区间,开启新的未闭合的区间。

  • 于是我们枚举两个值 dec,inc d e c , i n c 分别表示此时闭合区间的数量和将要开启新区间的数量。

  • 由于这 K K 个区间是互不相同的,我们要需要处理出其顺序带来的方案数。

  • 那么显然有转移式:

    f[i][j][k]CkdecCj+incinc=>f[i+1][j+inc][kdec+inc]

  • 其中 Cdeck C k d e c 表示在 k k 个未闭合的区间中选择 dec 来闭合增加的组合方案。

  • Cincj+inc C j + i n c i n c 表示新增的 inc i n c 个区间在总共的 j+inc j + i n c 个区间中的排列顺序增加的组合方案。

  • 而每个容器的容量为 T T 的限制就相当于在任意时刻未闭合的区间数量不超过 T

  • 答案即为 f[n+1][k][0] f [ n + 1 ] [ k ] [ 0 ]

  • 时间复杂度 O(NK4) O ( N K 4 )

Code

#include<cstdio>
#include<cctype>
using namespace std;
typedef long long LL;
const int N=45,mo=1011110011;
int n,k,T;
int f[N][N][N],c[N][N];
inline int read()
{
    int X=0,w=0; char ch=0;
    while(!isdigit(ch)) w|=ch=='-',ch=getchar();
    while(isdigit(ch)) X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
    return w?-X:X;
}
int main()
{
    freopen("container.in","r",stdin);
    freopen("container.out","w",stdout);
    n=read(),k=read(),T=read();
    for(int i=0;i<N;i++) c[i][0]=1;
    for(int i=1;i<N;i++)
        for(int j=1;j<=i;j++) c[i][j]=(c[i-1][j]+c[i-1][j-1])%mo;
    f[0][0][0]=1;
    for(int i=0;i<=n;i++)
        for(int j=0;j<=k;j++)
            for(int l=0;l<=j && l<=T;l++)
                if(f[i][j][l])
                    for(int inc=0;j+inc<=k;inc++)
                        for(int dec=0;dec<=l;dec++)
                            if(l-dec+inc<=T)
                                f[i+1][j+inc][l-dec+inc]=(f[i+1][j+inc][l-dec+inc]+
                                    (LL)f[i][j][l]*c[l][dec]%mo*c[j+inc][inc]%mo)%mo;
    printf("%d",f[n+1][k][0]);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值