1 条题解
-
0
自动搬运
来自洛谷,原作者为

ZhongYuLin
天若有情天亦老,人间正道是沧桑搬运于
2025-08-24 22:36:18,当前版本为作者最后更新于2024-09-06 15:23:28,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
考虑条件概率。具体地,设事件 表示所有点中一共有 个地雷,事件 表示所选点集中有 个地雷。根据条件概率的定义,我们要求的即为:
对于点 ,设其为地雷的概率为 ,构造生成函数 。容易用分治 FFT 求出 。要求出 ,实际上就是要维护下面的多项式:
$$\prod_{i=1}^n\prod_{j=1}^m\left [p_{i,j}x+(1-p_{i,j})\right] $$我们用线段树暴力维护区间卷积,合并时暴力 FFT,复杂度应该是 ,理论可以通过,实际上无法通过。
注意到 ,考虑精度损失。发现有效信息越来越少,可以直接忽略低于某一精度的值。使用线段树分治并暴力撤销而不进行多项式除法,只维护有效段并暴力卷积,可以通过本题。具体地,维护两个多项式,分别存储询问子集内的点的卷积与子集外的点的卷积。
分析复杂度。打表发现,当精度取 时,多项式内元素上界为 个,但远远达不到,可以通过。
#include<bits/stdc++.h> using namespace std; using ld=double; const int N=5e2+3; const ld eps=1e-14; struct Poly{ int l,r; deque<ld>q; Poly(){l=r=0;q.push_back(1);} void ins(ld p){ q.push_back(0);++r; for(auto it=--q.end();;--it){ *it*=1-p; if(it==q.begin())break; *it+=*prev(it)*p; } while(l<r&&q.front()<eps)q.pop_front(),++l; while(l<r&&q.back()<eps)q.pop_back(),--r; } ld operator[](int i){ if(i<l||i>r)return eps; return q[i-l]; } }now; #define id(x,y) ((x-1)*m+y) #define ls mid<<1 #define rs mid<<1|1 int n,m,K,q; ld a[N*N],b[N],c[N]; ld PA; set<int>t[N<<1]; void build(int l=1,int r=q,int p=1){ if(l==r){ int k,x,y; for(cin>>k;k--;){ cin>>x>>y; t[p].insert(id(x,y)); } return; } int mid=l+r>>1; build(l,mid,ls); build(mid+1,r,rs); for(auto x:t[ls])t[p].insert(x); for(auto x:t[rs])t[p].insert(x); } void solve(int l=1,int r=q,int p=1){ if(l==r){ Poly res; for(auto x:t[p])res.ins(a[x]); int len=t[p].size(),lim=min(K,len); if(!PA)for(int i=0;i<=lim;++i)PA+=res[i]*now[K-i]; for(int i=0;i<=lim;++i)printf("%.10lf ",res[i]*now[K-i]/PA); for(int i=K+1;i<=len;++i)printf("0 ");puts(""); return; } int mid=l+r>>1;Poly old=now; for(auto x:t[p])if(!t[ls].count(x))now.ins(a[x]); solve(l,mid,ls);now=old; for(auto x:t[p])if(!t[rs].count(x))now.ins(a[x]); solve(mid+1,r,rs);now=old; } int main(){ int u,v,w,x,y,z; ios::sync_with_stdio(0); cin.tie(0);cout.tie(0); cin>>n>>m>>K>>q;if(!q)return 0; for(int i=1;i<=n;++i)cin>>b[i]; for(int i=1;i<=m;++i)cin>>c[i]; build(); for(int i=1;i<=n;++i) for(int j=1;j<=m;++j){ a[id(i,j)]=b[i]+c[j]; if(!t[1].count(id(i,j))) now.ins(b[i]+c[j]); } solve(); return 0; }
- 1
信息
- ID
- 7485
- 时间
- 12000ms
- 内存
- 1024MiB
- 难度
- 7
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者