AT3860-[AGC020F]Arcs on a Circle【dp】

1|0正题

题目链接:https://www.luogu.com.cn/problem/AT3860


1|1题目大意

有一个周长为m的圆,n条线段,第i条长度为ai,将线段贴在圆的随机位置上,求整个圆都被覆盖的概率。

1n6,1m50


1|2解题思路

这种随机实数的问题我们可以从排名方面考虑。

先固定最长的一条线不动且左端点作为起点就可以不需要考虑环的问题了,然后对于每条线的开头离上一个整点的距离d进行一个排序,就可以作为每条线的排名了。

具体地,我们枚举一个排列作为排名,那这样就变为了n×m个点(每个排名),考虑用dp解决问题。

首先我们需要记录线段的使用状态,然后我们一个一个位置考虑线段是否填,然后还需要目前延伸到的最末尾位置。

fl,r,s表示目前填到l,最远延伸到r,线段使用状态为s时的概率,然后因为我们线段开头的排名是确定的,所以对于一个l只能有一条线段可以填,可以省去枚举这条线段的时间。

时间复杂度:O(n2m22nn!)

实际上常数很小,可以通过本题


1|3code

#include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; const double eps=1e-9; int n,m,cnt,a[10]; double ans,f[500][70]; int main() { freopen("circle.in","r",stdin); freopen("circle.out","w",stdout); scanf("%d%d",&n,&m); for(int i=0;i<n;i++) scanf("%d",&a[i]),a[i]=a[i]*n; sort(a,a+n); do{ int MS=(1<<n-1); for(int i=0;i<=n*m;i++) for(int s=0;s<MS;s++) f[i][s]=0; f[a[n-1]][0]=1; for(int i=1;i<=n*m;i++){ if(i%n==0)continue;int x=i%n-1; for(int j=i;j<=n*m;j++){ for(int s=0;s<MS;s++){ if(f[j][s]<eps||((s>>x)&1))continue; f[min(n*m,max(j,i+a[x]))][s|(1<<x)]+=f[j][s]; } } } ans+=f[n*m][MS-1];cnt++; }while(next_permutation(a,a+n-1)); printf("%.12lf",ans/(double)cnt/pow(m,n-1)); return 0; }

__EOF__

本文作者QuantAsk
本文链接https://www.cnblogs.com/QuantAsk/p/15884040.html
关于博主:退役OIer,GD划水选手
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   QuantAsk  阅读(24)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 张高兴的大模型开发实战:(一)使用 Selenium 进行网页爬虫
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
点击右上角即可分享
微信分享提示