AGC020F Arcs on a Circle
Description
你有一个长度为的圆,你在上面画了个弧。弧有长度。
每一条弧随机均匀地放置在圆上:选择圆上的一个随机实点,然后出现一条以该点为中心的长度为的弧。弧是独立放置的。例如,它们可以相互交叉或包含。
现在问你圆的每一个实点被至少一个弧覆盖的概率是多少?注意一条弧覆盖了它的两个端点。
Solution
的数量级小的时候变数就多了
一个常用的思想是将最长的一个圆弧的起点视为原点来避免跨原点的状态记录,而剩余的 个点的小数部分一定不是 且互不相同
现在的困境就在于判定圆弧相交,那么可以 枚举小数部分大小关系
那么将 个左右端点确定成成 个,不同的整数部分对应 个不同的小数部分
由于枚举了小数部分的大小关系,那么每个元素有确定的 个左端点可以使用
状压 来计算有多少种方案最终覆盖了整个圆即可:设 表示前 个单位的圆弧完成了覆盖,使用了 集合中的元素的方案数
按照左端点的顺序从小到大转移,每次添加左端点对应的元素,并将第一维根据添加的线段进行更新即可
注意新的第一维对 取
Code
int n,c;
int f[310][70],l[20],id[20];
signed main(){
n=read(); c=read();
rep(i,1,n) l[i]=read();
sort(l+1,l+n+1);
rep(i,1,n-1) id[i]=i;
double sum=0;
int U=1<<(n-1); --U;
do{
memset(f,0,sizeof(f));
f[l[n]*n][0]=1;
for(int i=1;i<=n*c;++i) if(i%n){
int now=id[i%n];
for(int j=i;j<=n*c;++j){
for(int S=0;S<=U;++S) if(!(S>>(now-1)&1)){
int pos=max(i+l[now]*n,j);
ckmin(pos,n*c);
f[pos][S|(1<<(now-1))]+=f[j][S];
}
}
}
sum+=f[c*n][U];
}while(next_permutation(id+1,id+n));
rep(i,1,n-1) sum/=c*i;
printf("%.14lf\n",sum);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律