题解 P6089 【[JSOI2015]非诚勿扰】
LSG_waterlyf · · 题解
设女生集合为
-
第一轮即被选中:
P1=(1-p)^{(i-1)} *p . -
第二轮:
P2:(1-p)^{(i-1+m)}*p , -
第
n 轮:Pn=(1-p)^{(i-1+m*(n-1) )}*p .
观察发现是等比数列,套公式得
因为
所以选中
接下来只要用权值树状数组维护逆序対即可。
#include<bits/stdc++.h>
using namespace std;
#define N 500100
#define ll long double
int n,m;
ll p,c[N],ans;
int lowbit(int x) {return x&-x;}
void change(int x,ll w)
{
while(x<N) c[x]+=w,x+=lowbit(x);
}
ll ask(int x)
{
ll val=0;
while(x) val+=c[x],x-=lowbit(x);
return val;
}
vector<int>g[N];
int main()
{
cin>>n>>m>>p;
for(int i=1,a,b;i<=m;i++)
scanf("%d%d",&a,&b),g[a].push_back(b);
for(int i=1;i<=n;++i) sort(g[i].begin(),g[i].end());
for(int i=1;i<=n;i++)
{
if(!g[i].size()) continue;
int k=g[i].size(),x;
for(int j=0;j<k;j++)
{
x=g[i][j];
ll pos=pow(1-p,j)*p/(1-pow(1-p,k));
// printf("girl==%d boy==%d p==%Lf\n",i,x,pos);
ans+=pos*(ask(n)-ask(x));
}
for(int j=0;j<k;j++)
{
x=g[i][j];
ll pos=pow(1-p,j)*p/(1-pow(1-p,k));
change(x,pos);
}
}
printf("%.2Lf",ans);
return 0;
}