- 2025-06-10
本场的题解(劳N没有把题目开放,所以我只好写在这里了,生蚝会写ABCD的题解)
- @ 2025-6-12 9:19:24
E
显然我们考虑每个格子的贡献,说白了这个题就是让你把每个点被涂黑的概率加起来,这很好理解。
然后我们考虑第 行第 列的贡献,其实就是如果选的两个格子在其左上,右上,左下,右下的话就一定能覆盖掉这个格子,这一部分的贡献是 ,然后我们要减去两个选择的格子在同一行和同一列的贡献,因为他们被计算了两次,也就是,最后加加减减一些常数(具体我也不好说,因为这个题是否允许两个格子相等也并不明确)
然后这是如果只选一次,它能够变黑的概率,那么次只要有一次变黑它就黑了,所以我们只需要计算 ,就可以退出来它变黑的概率统计增加即可。
F
神仙题
首先我们先忽略精度问题,考虑直接硬干怎么做。发现这个 真的很难办,我们不妨把它的贡献拆开。注意到!!!这个东西它的贡献其实可以理解为这 个行或列构成的集合中选出一个子集的方案。然后这个题就快做完了,我们只需要枚举每一个可能的子集,计算它带来的贡献就赢了,具体贡献方式我会放出来代码。
然后还有一些实现细节我都在代码里体现。
CODE
#include<bits/stdc++.h>
#define ld long double
using namespace std;
int n,m,k;
ld res;
ld lnfac[1000005];
inline ld lnC(int n,int m){return lnfac[n]-lnfac[n-m]-lnfac[m];}
int main(){
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=m;i++)lnfac[i]=lnfac[i-1]+log(1.0*i);//这个有点厉害,我们可以直接取ln,避免后面精度丢失更为严重的乘法和除法。
for(int i=0;i<=n;i++){
for(int j=0;j<=n;j++){
int num=i*n+j*n-i*j;
if(num<=k)res+=exp(lnC(n,i)+lnC(n,j)/*前面是部分一*/+lnC(m-num,k-num)/*这是部分二*/-lnC(m,k));
//我来具体说一下贡献方式,首先我们枚举行和列分别为 $i$ $j$ ,然后我们考虑从n行n列里面把他选出来(对应上面的部分1),这个时候剩下的随便选
//考虑剩下来的怎么个随便选法,其实就是从总个数m里面先挖去已经确定的位置 $num$ ,然后从里面选出来剩下的 $0$ 也就是 $k-num$
//这个时候你可能会问,它题目不是先往里面填互不相同的数么?你这样不就只剩下01了?对,但是你注意到这两个问题其实是等价的,我不好证明,因为我直观感觉这很对。
}
}
if(res>1e99)res=1e99;
printf("%.6Lf",res);
return 0;
}
1 条评论
-
kkksc03wzl LV 7 @ 2025-6-21 14:47:12
神仙题
- 1