题解 P6089 【[JSOI2015]非诚勿扰】
不至于没有题解吧。。。
首先假设一个女性中意
对于第一个男性,选中的概率
等比数列求和得
且
从小到大考虑每个女性
这就是个单点加,询问后缀和。树状数组维护即可。
复杂度
PS:有点卡精度,我用 double 90pts,long double 就过了
#define MAXN 500011
int n;
struct BIT
{
long double t[MAXN];
#define lowb (i&-i)
void modify(int i,long double k)
{
while(i<=n)t[i]+=k,i+=lowb;
}
long double Qsum(int i)
{
long double res=0;
while(i)res+=t[i],i-=lowb;
return res;
}
}t;
std::vector<int>a[MAXN];
long double Qpow(long double x,int p)
{
long double res=1;
while(p)
{
if(p&1)res*=x;
x*=x,p>>=1;
}
return res;
}
int main()
{
n=read();
int m=read();
double tmp;
scanf("%lf",&tmp);
long double p=tmp,ans=0;
for(int i=1;i<=m;++i)
{
int u=read(),v=read();
a[u].push_back(v);
}
for(int u=1;u<=n;++u)
{
if(a[u].empty())continue;
std::sort(a[u].begin(),a[u].end());
long double now=p/(1-Qpow(1-p,a[u].size()));
for(int v:a[u])
{
ans+=t.Qsum(n-v)*now;
now*=(1-p);
}
now=p/(1-Qpow(1-p,a[u].size()));
for(int v:a[u])
{
t.modify(n-v+1,now);
now*=(1-p);
}
}
printf("%.2lf",tmp=ans);
return 0;
}