题解:P8139 [ICPC2020 WF] Sweep Stakes
ZhongYuLin · · 题解
考虑条件概率。具体地,设事件
对于点
我们用线段树暴力维护区间卷积,合并时暴力 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;
}