Atcoder 题面传送门 & 洛谷题面传送门

一道难度 unavailable 的 AGC F 哦

首先此题最棘手的地方显然在于此题的坐标可以为任意实数,无法放入 DP 的状态,也无法直接计算概率。我们考虑是否能将实数坐标转化为我们熟知的整数坐标。这里有一个套路,注意到每条弧的长度都是整数这个条件,考虑两个坐标 \(A,B\),显然以 \(A\) 开始的长度为 \(l\) 的弧能覆盖到 \(B\) 当且仅当 \(\lfloor B\rfloor-\lfloor A\rfloor<l\),或者 \(\lfloor B\rfloor-\lfloor A\rfloor=l\) 且 \((B-\lfloor B\rfloor)<(A-\lfloor A\rfloor)\)。这就告诉我们,坐标的小数部分具体是什么并不重要,我们只关心它们的相对大小。又因为小数部分为取值范围为 \([0,1)\) 的连续性变量,因此出现两点小数部分相同的概率可以视作 \(0\),因此我们暴力枚举这 \(n\) 条线段小数部分的相对大小——共有 \(n!\) 种可能的情况,它们是等可能的(yyq 既视感),计算出它们覆盖整个圆周的概率后除以 \(n!\) 即可。

接下来考虑给定这 \(n\) 条线段小数部分的相对大小后怎样计算概率,首先我们固定住一条线段的位置,这样即可实现断环成链,其次由于我们已经知道了它们的相对大小了,所以最多只可能有 \(nc\) 个起点位置,故可将 \(c\) 个坐标拆成 \(nc\) 个并将线段覆盖转化为点覆盖——这个异常容易理解。我们强制要求小数部分相对大小排名为 \(k\) 的线段只能在 \(tn+k(t\in\mathbb{Z})\) 的位置作为起始位置。这样就可以 \(dp\) 了,设 \(dp_{i,j,k}\) 表示现在覆盖了起点坐标 \(\leq i\) 的线段,当前覆盖到的右端点的最大值为 \(j\),当前使用的线段集合为 \(k\)(这个状态设计感觉有点像此题),转移就分 \(i\) 处不放线段和放线段两种情况转移即可,显然如果 \(i\) 处放线段,那放置的线段是唯一的(\(i\bmod n\)),因此总复杂度 \(n!\times 2^n\times n\times c\),由于此题 \(n\) 数据范围极小,可通过此题。

最后值得一提的是不少题解都没有提到一点,就是为什么一定要强制令长度最大的线段的起点为圆周的起始位置,这里稍微讲下,因为假设我们用一个长度较小的线段作为圆周的起始位置,根据我们的 DP 过程可知对于线段超过断成的链的部分我们会直接忽略,但有可能会出现长度较大的线段从链的末尾开始覆盖,由于这是一个圆周,因此多出的部分又绕回链的开头,补上链开头线段覆盖的空隙的情况,这种情况是不会被我们纳入总方案的,不过 in fact 这种方案也是合法的。而使用长度最大的线段作为开头就恰好避免的这种情况,因此需要强制令长度最大的线段的起点为圆周的起始位置。

似乎 WC2021 的时候 lyx 神仙给出了一个更优秀的解法,要什么高级插值技巧什么的,not for me,thx

#include <bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define fill0(a) memset(a,0,sizeof(a))
#define fill1(a) memset(a,-1,sizeof(a))
#define fillbig(a) memset(a,63,sizeof(a))
#define pb push_back
#define ppb pop_back
#define mp make_pair
template<typename T1,typename T2> void chkmin(T1 &x,T2 y){if(x>y) x=y;}
template<typename T1,typename T2> void chkmax(T1 &x,T2 y){if(x<y) x=y;}
typedef pair<int,int> pii;
typedef long long ll;
typedef unsigned int u32;
typedef unsigned long long u64;
namespace fastio{
#define FILE_SIZE 1<<23
char rbuf[FILE_SIZE],*p1=rbuf,*p2=rbuf,wbuf[FILE_SIZE],*p3=wbuf;
inline char getc(){return p1==p2&&(p2=(p1=rbuf)+fread(rbuf,1,FILE_SIZE,stdin),p1==p2)?-1:*p1++;}
inline void putc(char x){(*p3++=x);}
template<typename T> void read(T &x){
x=0;char c=getchar();T neg=0;
while(!isdigit(c)) neg|=!(c^'-'),c=getchar();
while(isdigit(c)) x=(x<<3)+(x<<1)+(c^48),c=getchar();
if(neg) x=(~x)+1;
}
template<typename T> void recursive_print(T x){if(!x) return;recursive_print(x/10);putc(x%10^48);}
template<typename T> void print(T x){if(!x) putc('0');if(x<0) putc('-'),x=~x+1;recursive_print(x);}
void print_final(){fwrite(wbuf,1,p3-wbuf,stdout);}
}
const int MAXN=6;
const int MAXC=50;
int n,l[MAXN+2],c,p[MAXN+2];
ll dp[MAXN*MAXC+5][(1<<MAXN)+5];
int main(){
scanf("%d%d",&n,&c);ll ret=0;
for(int i=0;i<n;i++) scanf("%d",&l[i]),p[i]=i;
sort(l,l+n);reverse(l,l+n);
do {
memset(dp,0,sizeof(dp));dp[l[p[0]]*n][1]=1;
for(int i=1;i<n*c;i++) for(int j=i;j<=n*c;j++){
int t=i%n;
for(int k=0;k<(1<<n);k++) if(~k>>t&1)
dp[min(n*c,max(j,i+l[p[t]]*n))][k|(1<<t)]+=dp[j][k];
} ret+=dp[n*c][(1<<n)-1];
} while(next_permutation(p+1,p+n));
double ans=ret;//printf("%lld\n",ret);
for(int i=1;i<=n-1;i++) ans=1.*ans/i;
for(int i=2;i<=n;i++) ans=1.*ans/c;
printf("%.17lf\n",ans);
return 0;
}

Atcoder Grand Contest 020 F - Arcs on a Circle(DP+小技巧)的更多相关文章

  1. Atcoder Grand Contest 030 F - Permutation and Minimum(DP)

    洛谷题面传送门 & Atcoder 题面传送门 12 天以前做的题了,到现在才补/yun 做了一晚上+一早上终于 AC 了,写篇题解纪念一下 首先考虑如果全是 \(-1\)​ 怎么处理.由于我 ...

  2. Atcoder Grand Contest 024 E - Sequence Growing Hard(dp+思维)

    题目传送门 典型的 Atcoder 风格的计数 dp. 题目可以转化为每次在序列中插入一个 \([1,k]\) 的数,共操作 \(n\) 次,满足后一个序列的字典序严格大于前一个序列,问有多少种操作序 ...

  3. AtCoder Grand Contest 002 F:Leftmost Ball

    题目传送门:https://agc002.contest.atcoder.jp/tasks/agc002_f 题目翻译 你有\(n*k\)个球,这些球一共有\(n\)种颜色,每种颜色有\(k\)个,然 ...

  4. AtCoder Grand Contest 017 F - Zigzag

    题目传送门:https://agc017.contest.atcoder.jp/tasks/agc017_f 题目大意: 找出\(m\)个长度为\(n\)的二进制数,定义两个二进制数的大小关系如下:若 ...

  5. AtCoder Grand Contest 003 F - Fraction of Fractal

    题目传送门:https://agc003.contest.atcoder.jp/tasks/agc003_f 题目大意: 给定一个\(H×W\)的黑白网格,保证黑格四连通且至少有一个黑格 定义分形如下 ...

  6. AtCoder Grand Contest 011 F - Train Service Planning

    题目传送门:https://agc011.contest.atcoder.jp/tasks/agc011_f 题目大意: 现有一条铁路,铁路分为\(1\sim n\)个区间和\(0\sim n\)个站 ...

  7. AtCoder Grand Contest 010 F - Tree Game

    题目传送门:https://agc010.contest.atcoder.jp/tasks/agc010_f 题目大意: 给定一棵树,每个节点上有\(a_i\)个石子,某个节点上有一个棋子,两人轮流操 ...

  8. AtCoder Grand Contest 016 F - Games on DAG

    题目传送门:https://agc016.contest.atcoder.jp/tasks/agc016_f 题目大意: 给定一个\(N\)点\(M\)边的DAG,\(x_i\)有边连向\(y_i\) ...

  9. Atcoder Grand Contest 038 F - Two Permutations(集合划分模型+最小割)

    洛谷题面传送门 & Atcoder 题面传送门 好久前做的题了--今天偶然想起来要补个题解 首先考虑排列 \(A_i\) 要么等于 \(i\),要么等于 \(P_i\) 这个条件有什么用.我们 ...

随机推荐

  1. I-Base62

    I - Base62 PS:一个任意进制转换的大数问题 传送门:Base62 短除法原理: 20(10进制) => 202(3进制) 20 = (2 * 3 ^ 2 + 0 * 3 ^ 1 + ...

  2. 【Java虚拟机6】Java内存模型(Java篇)

    什么是Java内存模型 <Java虚拟机规范>中曾试图定义一种"Java内存模型"(Java Memory Model,JMM)来屏蔽各种硬件和操作系统的内存访问差异, ...

  3. Coursera Deep Learning笔记 改善深层神经网络:超参数调试 正则化以及梯度相关

    笔记:Andrew Ng's Deeping Learning视频 参考:https://xienaoban.github.io/posts/41302.html 参考:https://blog.cs ...

  4. kviy TextInput 触发事件

    from kivy.uix.widget import Widget from kivy.app import App from kivy.lang import Builder Builder.lo ...

  5. java监控JVM的内存使用情况等

    以下的程序监控参数的代码,有些是从网络上获取的,此处进行一个记录是为了以后如果要用到方便记录. 1.引入jar包,为了获取一些cpu的使用率等信息 <dependency> <gro ...

  6. 人人都写过的5个Bug!

    大家好,我是良许. 计算机专业的小伙伴,在学校期间一定学过 C 语言.它是众多高级语言的鼻祖,深入学习这门语言会对计算机原理.操作系统.内存管理等等底层相关的知识会有更深入的了解,所以我在直播的时候, ...

  7. Less3

    继续第三关的学习 1.根据第一关的记录,我们判断出是什么注入 id=1' and '1'='1 id=1' and '1'='2 返回不同,所以存在字符型的注入 2. 这时候我们再用正常的报错猜解准备 ...

  8. QT判断文件/目录是否存在

    最近在用qt写一个ui,遇到删除sd卡中的文件失败情况,有些时候是存在删除链表里面的文件在sd卡上已经不存在了,导致失败,以为我的链表是定时刷新的,但是文件是实时更新会同步覆盖的.这样就存在可能上一秒 ...

  9. python中将xmind转成excel

    需求:最近公司项目使用tapd进行管理,现在遇到的一个难题就是,使用固定的模板编写测试用例,使用excel导入tapd进行测试用例管理,觉得太过麻烦,本人一直喜欢使用导图来写测试用例,故产生了这个工具 ...

  10. 🏆【JVM深层系列】「云原生时代的Java虚拟机」针对于GraalVM的技术知识脉络的重塑和探究

    GraalVM 背景 新.旧编程语言的兴起躁动,说明必然有其需求动力所在,譬如互联网之于JavaScript.人工智能之于Python,微服务风潮之于Golang等等.大家都清楚不太可能有哪门语言能在 ...