【xsy1503】 fountain DP
题目大意:给你D个格子,有n个喷水器,每个喷水器有一个喷水距离ri。
现在你需要在这D个格子中选择n个位置按照任意顺序安装这n个喷水器,需要满足n个喷水器互相喷不到对方。
问方案数,对109+7取模
数据范围:n,ri≤40,D≤105
我们不妨考虑我们钦定了这n个喷水器的出现顺序,从左到右第i个喷水器编号为p[i]。
确定排列顺序后,令d=n−1∑i=1max(rp[i],rp[i+1])
我们发现上式累加的实际上是相邻两个喷水器之间的最小间隔
我们尝试把这个间隔中的格子看成是一个格子。
我们就可以把原序列中D个格子看成是D−d−1个了。
现在也就是变成了要在这剩下的格子之间插入这n个喷水器,方案数显然为(D−d−1+nn)。
下面考虑如何求不同的排列顺序数量。
我们先将n个喷水器按照喷水半径进行排序。
设f[i][j][k]表示前i个喷水器必须出现,且这i个喷水器间(包括两端),有j个可以插入喷水器,且由这些喷水器累加出的d为k的方案数量。
下面考虑在f[i][j][k]的基础上插入第i+1个喷水器。
假定这个喷水器插入后,两侧不能再插入喷水器,则有f[i+1][j−1][k+2ri+1]+=f[i][j][k]×(j−2)
假定这个喷水器插入后,只有一侧能插入喷水器,则有f[i+1][j][k+ri+1]+=f[i][j][k]×(2j−2)
上面两个转移需要−2的原因显然(并不能允许最左侧和最右侧插入喷水器)
假定这个喷水器插入后,两侧皆可以插入喷水器,则有f[i+1][j+1][k]+=f[i][j][k]×j
初始情况:f[1][2][0]=1,答案为∞∑i=1f[n][2][i]
转移和答案统计的时候记得取模即可
时间复杂度:O(n2n∑i=1ri)
1 #include<bits/stdc++.h> 2 #define M 42 3 #define N 110000 4 #define L long long 5 #define MOD 1000000007 6 using namespace std; 7 8 L pow_mod(L x,L k){L ans=1; for(;k;k>>=1,x=x*x%MOD) if(k&1) ans=ans*x%MOD; return ans;} 9 L fac[N]={0},invfac[N]={0}; 10 L C(int n,int m){if(n-m<0) return 0; return fac[n]*invfac[m]%MOD*invfac[n-m]%MOD;} 11 12 int n,D,r[M]={0}; 13 L f[M][M][M*M]={0}; 14 15 16 int main(){ 17 fac[0]=1; for(int i=1;i<N;i++) fac[i]=fac[i-1]*i%MOD; 18 invfac[N-1]=pow_mod(fac[N-1],MOD-2); 19 for(int i=N-2;~i;i--) invfac[i]=invfac[i+1]*(i+1)%MOD; 20 21 scanf("%d%d",&n,&D); 22 for(int i=1;i<=n;i++) scanf("%d",r+i); 23 sort(r+1,r+n+1); 24 f[1][2][0]=1; 25 for(int i=1;i<n;i++) 26 for(int j=0;j<=n+2;j++) 27 for(int k=0;k<M*M;k++) 28 if(f[i][j][k]){ 29 (f[i+1][j+1][k]+=f[i][j][k]*j)%=MOD; 30 if(j>1) (f[i+1][j-1][k+2*r[i+1]]+=f[i][j][k]*(j-2))%=MOD; 31 if(j>1) (f[i+1][j][k+r[i+1]]+=f[i][j][k]*(2*j-2))%=MOD; 32 } 33 L ans=0; 34 for(int d=0;d<M*M;d++) 35 if(f[n][2][d]){ 36 (ans+=C(D-d-1+n,n)*f[n][2][d])%=MOD; 37 } 38 cout<<ans<<endl; 39 }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!