【xsy2425】容器 dp

题目大意:有n个人,区间大小为m,每个人必须覆盖一段区间[li,ri],问你存在多少种不同的覆盖方案,使得区间上每个位置被覆盖的次数不超过t

两种方案被定义为不同当且仅当存在第i个人覆盖的区间不同。

求方案数,对一个质数取模。

数据范围:n,m,t40

 

我们考虑dp。

f[i][j][k]表示区间的前i个位置,总共有j个人参与了覆盖,且有k个人同时覆盖了位置i,位置i+1的方案数。

我们考虑枚举JK,需要保证j<J

那么我们显然可以用f[i][j][k]的值去更新f[i+1][J][K]的值。

f[i][j][k]f[i+1][J][K],用的人数多了Jj个,我们要从nj个人中选出Jj个人去增加总人数,方案数显然为(njJj)

然后,我们还要保证有K个人可以覆盖到i+2,而这K个人显然只能从k+(Jj)个人中选出,方案数显然为(k+(Jj)K)

那么转移方程大概长这样:

f[i+1][J][K]+=f[i][j][k]×(njJj)×(Jj+kK)

复杂度为O(nk4)

复制代码
 1 #include<bits/stdc++.h>
 2 #define L long long
 3 #define M 55
 4 #define MOD 1011110011
 5 using namespace std;
 6  
 7 L n,m,t,c[M][M]={0},f[M][M][M]={0};
 8  
 9 int main(){
10     for(int i=0;i<M;i++){
11         c[i][0]=1;
12         for(int j=1;j<=i;j++) c[i][j]=(c[i-1][j]+c[i-1][j-1])%MOD;
13     }
14     cin>>n>>m>>t;
15     f[0][0][0]=1;
16     for(int i=0;i<n;i++)
17     for(int j=0;j<=m;j++)
18     for(int k=0;k<=j;k++)
19     if(f[i][j][k]){
20         for(int J=j;J<=m;J++)
21         for(int K=0;K<=J;K++){
22             int cnt=J-j+k;
23             if(cnt>t) continue;
24             (f[i+1][J][K]+=f[i][j][k]*c[m-j][J-j]%MOD*c[cnt][K]%MOD)%=MOD;
25         }
26     }
27     cout<<f[n][m][0]<<endl;
28 }
复制代码

 

posted @   AlphaInf  阅读(150)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!
点击右上角即可分享
微信分享提示