1 条题解

  • 0
    @ 2026-8-27 10:32:24

    Solution\texttt{Solution}

    首先,可以利用等比数列求和公式,因为 0.4P<0.60.4\le P<0.6,删去分子上的 A(q+1)A(q+1) 算出每对男女 (i,j)(i,j) 在一起的概率。询问时倒叙插入,并用树状数组维护。 比如对于一个女生 aa,有 kk 个候选男生编号为 1k1\ldots k,那么对于第 mm 个男生,(a,m)(a,m) 在一起的概率就是

    $$(1-p)^{m-1}\times p+(1-p)^k\times (1-p)^{m-1}\times p+(1-p)^{2k}\times (1-p)^{m-1}\times p+\ldots+(1-p)^{x-1}\times (1-p)^{m-1}\times p$$

    分别随对应在第 11 轮、第 22 轮、第 33 轮…第 xx 轮选中第 mm 个男生的概率,其中 xx 需要到正无穷。不难发现,其实这是一个以 (1p)(m1)×p(1-p)^{(m-1)}\times p 为首项,(1p)k(1-p)^{k} 为公比的等比数列,我们要所得就是对这个数列求和。不妨先利用等比数列求和公式:

    Sn=a1×1qn1qS_n=a_1\times\frac{1-q^{n}}{1-q}

    其中,a1=(1p)m1a_1=(1-p)^{m-1}。瓶颈在于 nn 趋向正无穷,无法精确求出。因为 q=(1p)kq=(1-p)^k0.4<1p<0.60.4<1-p<0.6 不接近 11,那么当 nn 很大时,qnq^n 非常接近于 00,因为只需要保留 22 位小数,不妨把 qnq^n 当做 00。那么,答案就是 a1÷(1q)a_1\div(1-q)

    这样我们就求出了每队男女在一起的概率。

    至于统计答案,原始想法是枚举每组不稳定的配对关系,算出概率和计可,但是这样只能通过 60%60\% 的数据。我们可以倒序枚举女生,使用树状数组或线段树维护后 ii 个女生与前 jj 个女生配对的概率和。最多操作 MM 次插入 MM 次询问,即可通过全部数据。

    Code\texttt{Code}

    #include<bits/stdc++.h>
    using namespace std;
    const int N=6e5+7;
    int lowbit(int x){ return x&(-x); }
    int n,m,d[N],c[N],pt;
    double p,pw[N],ans;
    struct Node{
    	double a[N];
    	double sum(int p){
    		double ans=0;
    		for(;p;p-=lowbit(p)) ans+=a[p];
    		return ans;
    	}
    	void modefy(int p,double val){
    		p++;
    		for(;p<=n;p+=lowbit(p))  a[p]+=val;
    	}
    }t;
    struct Edge{
    	int u,v;
    	double p;
    	Edge(){}
    	Edge(int u,int v,double p):u(u),v(v),p(p){};
    }e[N];
    int main(){
    	ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
    	cin>>n>>m>>p;
    	for(int i=0,u,v;i<m;i++) cin>>u>>v,u--,v--,d[u]++,e[i]=Edge(u,v,0);
    	sort(e,e+m,[](Edge x,Edge y){if(x.u!=y.u) return x.u<y.u; else return x.v<y.v;});
    	pw[0]=1.0;
    	for(int i=0;i<n;i++) pw[i+1]=pw[i]*(1-p);
    	for(int i=0,u;i<m;i++){
    		u=e[i].u;
    		e[i].p=p*pw[c[u]]/(1-pw[d[u]]);
    		c[u]++;
    	}reverse(e,e+m);
    	for(int i=n-1;i>=0;i--){
    		for(int j=pt;j<m&&e[j].u==i;j++) ans+=t.sum(e[j].v)*e[j].p;
    		for(int j=pt;j<=m&&e[j].u==i;j++) t.modefy(e[j].v,e[j].p),pt=j+1;
    	}
    	cout<<fixed<<setprecision(2)<<ans<<endl;
    	return 0;
    }
    

    管理员大大大辛苦了。

    ~本蒟蒻的第一篇题解,点个赞再走吧QAQ~

    第一篇题解,有勘误请指出qwq

    • 1

    信息

    ID
    6146
    时间
    2000ms
    内存
    500MiB
    难度
    10
    标签
    递交数
    2
    已通过
    1
    上传者