1 条题解

  • 0
    @ 2025-8-24 21:53:51

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar wlj_55
    **

    搬运于2025-08-24 21:53:51,当前版本为作者最后更新于2019-10-16 12:05:51,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    传送门

    题意简述

    有两个数x,yx,y,其中xx是随机生成的[0,n)[0,n)间一个正整数,yypp的概率为[0,n)[0,n)间一个数,使得x xor yx\space xor\space y最大,有(1p)(1-p)的概率生成方式同xx,求x xor yx\space xor \space y的期望值。

    解题思路

    我们先考虑暴力的解法。

    35pts

    n100n\le100,随便怎么暴力都可以过。

    p=0p=0时,即求

    $$\frac{\sum_{i=1}^n\sum_{j=1}^n i\space xor\space j}{n^2} $$

    直接两重循环求解即可,时间复杂度O(n2)O(n^2),记得开doubledouble

    p=1p=1时,我们只需对上述情况的第二层循环做出微调,将求和改为求最大值,再讲每一个ii所对应的最大值分别相加即可。

    代码略。

    50pts

    我们可以观察到后面15pts15pts的数据是2k2^k的形式,那么它们间一定有着一些特殊规律。

    打表检验得:

    p=0p=0时,答案为n12\frac{n-1}{2}

    p=1p=1时,答案为n1n-1

    下面给出证明:

    首先,在p=1p=1时,对于每个数xx,总有一个数y[0,n)y∈[0,n)使得x xor y=n1x\space xor \space y=n-1,所以期望为n(n1)n=n1\frac{n(n-1)}{n}=n-1

    p=0p=0时,我们首先有一个结论:

    $$x\space xor\space i+x\space xor\space (2^k-i-1)=2^k-1\qquad i∈[0,2^k) $$

    证明也很简单,手玩一下就好了。

    所以我们对[0,n)[0,n)间数两两配对,求得期望为$\frac{n\times \frac{n\times(n-1)}{2}}{n^2}=\frac{n-1}{2}$

    100pts

    由于这里有0p10\le p\le1的情况,所以我们要先解决这种情况。

    PP为总的期望值,P1P_1pp00时的期望,P2P_2pp11时的期望,

    由期望的一些基本知识可以很容易的推出

    P=(1p)×P1+p×P2P=(1-p)\times P_1+p\times P_2

    那么下面就是如何计算P1,P2P_1,P_2的问题了。

    先讨论p=0p=0时的情况,

    我们设对于两个数异或起来的值,第ii位为11为事件AA,第jj位为11为事件BB,由位运算的性质知A,BA,B相互独立,故我们可以分开计算。

    我们再设从[0,n)[0,n)中选出一个数,其二进制第ii位为11的概率为pip_i,那么刚才的答案就是

    $$\sum_{i=0}^{\log n}2\times p_i\times (1-p_i)\times2^i $$

    考虑对于区间[0,2k)[0,2^{k}),一定有区间[0,2k1)[0,2^{k-1})的所有数的第kk位均为00,区间[2k1,2k)[2_{k-1},2^k)的所有数第kk位均为11

    然后我们考虑区间[0,n)[0,n),那么必定有区间[S×2k,S×2k+2k1)[S\times 2^{k},S\times2^k+2^{k-1})中的数第kk位为0,区间[S×2k+2k1,(S+1)×2k+1)[S\times2^k+2^{k-1},(S+1)\times2^{k+1})中数的第kk位为0,所以第kk位为1的数的个数是:

    $$\lfloor\frac{n}{2^{k+1}}\rfloor\times 2^k+max(n\space mod\space2^{k+1}-2^k,0) $$

    故概率pip_i

    $$\frac{\lfloor\frac{n}{2^{k+1}}\rfloor\times 2^k+max(n\space mod\space2^{k+1}-2^k,0)}{n} $$

    时间复杂度O(logn)O(\log n)

    我们再来考虑p=1p=1时的情况(比较毒瘤

    我们设f(x)f(x)[0,n)[0,n)内使x xor f(x)x\space xor\space f(x)最大的f(x)f(x)的值

    如果没有范围的限制的话,f(x)f(x)应为xx按位取反后的值,现在多了一个nn的限制,那我们可以考虑用一种贪心的手法保留高位的11,如果某一位取11会使f(x)nf(x)\ge n,那么这一位就只能取00

    我们考虑最高的i1i-1(i10)(i-1\ge0)n1n-1的前(i1)(i-1)位相同的所有的xx对答案的贡献,我们考虑n1n-1xx的第ii位,有下列情况:

    1.n11.n-1的第ii位为00,由于xn1,f(x)n1x\le n-1,f(x)\le n-1,所以xx的第ii位和f(x)f(x)的第ii位必须为00

    2.n12.n-1的第ii位为11,那么xxii位的取值又可以分两种情况:

    :x:x的第ii位为11,那么f(x)f(x)的第ii位为00,且以后的位数一定可以取xx取反后的值。

    :x:x的第ii位为00,那么f(x)f(x)的第ii位为11,但还有后面的限制。

    每次处理时n1n-1的规模将减半,故时间复杂度为O(logn)O(\log n)

    Code

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    double solve1(ll n){
    	double ret=0;
    	ll Pow=0,tmp=n-1;
    	while(tmp!=0){
    		Pow++;
    		tmp>>=1;
    	}
    	for(int i=Pow;i>0;i--){
    		ll nw=(n>>i)*(1LL<<i-1)+min(n-(n>>i<<i),1LL<<i-1);
    		double p=double(n-nw)/n;
    		ret+=(1.0-p)*(1LL<<(i-1))*p;
    	}
    	return ret*2.0;
    }
    double solve2(ll n){
    	if(n==1)  return 0.0;
    	double ret=0.0;
    	ll v=1LL,delta,num,tmp=n-1;
    	n--;
    	while(v<=tmp){
    		v<<=1;
    	}
    	delta=v-1LL;
    	v>>=1;
    	ret+=(double)delta*(n-v+1);
    	ret+=(double)v*v;
    	num=v,delta>>=1;
    	while(v!=1){
    		v>>=1,delta>>=1;
    		if(n&v){
    			ret+=(double)num*v;
    			ret+=(double)(num>>1)*delta;
    			num>>=1;
    		}
    		else
    		  ret+=(double)(num>>1)*v;
    	}
    	return ret/(double)(n+1);
    }
    int main(){
    	ll n;
    	double p;
    	scanf("%lld%lf",&n,&p);
    	double p1=solve1(n),p2=solve2(n),ans=(1.0-p)*p1+p*p2;
    	printf("%.6lf\n",ans);
    }
    
    

    如果大家有不懂的可以问我,我会尽我所能解答。

    • 1

    信息

    ID
    2855
    时间
    1000ms
    内存
    128MiB
    难度
    5
    标签
    递交数
    0
    已通过
    0
    上传者